堆排序与数据结构中的堆
作者:洗个小枣_312 | 来源:互联网 | 2024-12-24 15:41
堆是一种常见的数据结构,广泛应用于计算机科学领域。它通常表示为一棵完全二叉树,并可通过数组实现。堆的主要特性是每个节点的值与其父节点的值之间存在特定的关系,这使得堆在优先队列和排序算法中非常有用。
堆(heap)是一种特殊的数据结构,其特点是可以通过数组来表示一棵完全二叉树。堆的主要性质包括:
1. **父子节点关系**:对于最大堆,每个节点的值都不小于其子节点的值;对于最小堆,每个节点的值都不大于其子节点的值。
2. **完全二叉树**:堆总是一棵完全二叉树,这意味着除了最后一层外,所有层都是满的,且最后一层的节点尽可能靠左排列。
### 堆的分类
根据根节点的值,堆可以分为两种类型:
- **最大堆(大顶堆)**:根节点是堆中最大的元素。
- **最小堆(小顶堆)**:根节点是堆中最小的元素。
常见的堆实现包括二叉堆、斐波那契堆等。二叉堆是最常用的堆实现方式之一,它通过数组存储,并且满足以下条件:
设一个包含n个元素的序列{k1, k2, ..., kn},当且仅当满足以下关系时,该序列为堆:
- 对于最大堆:ki >= k2i 和 ki >= k2i+1 (i = 1, 2, ..., n/2)
- 对于最小堆:ki <= k2i 和 ki <= k2i+1 (i = 1, 2, ..., n/2)
### 堆的操作
堆支持多种操作,包括但不限于:
- **build**:创建一个空堆。
- **insert**:向堆中插入新元素。
- **update**:调整新元素的位置以保持堆的性质。
- **get**:获取当前堆顶元素的值。
- **delete**:删除堆顶元素。
- **heapify**:在删除堆顶元素后重新调整堆以保持其性质。
某些堆实现还支持其他操作,如检查堆中是否存在某个元素。
### 建堆效率
对于包含n个节点的堆,高度d = log₂n。建堆的时间复杂度为O(n),因为大部分节点位于树的底部,而这些节点不需要移动。插入、删除普通元素和删除最小元素的平均时间复杂度为O(log n)。
### 堆的应用
堆广泛用于动态内存分配和释放,特别是在程序需要动态分配对象时。例如,当程序所需对象的数量和大小事先未知,或对象太大不适合使用栈分配器时,堆是一个很好的选择。
在操作系统和运行时库中,堆用于管理进程内的内存分配。默认情况下,操作系统会为每个进程创建一个称为进程堆的默认堆。此外,应用程序或加载的动态链接库(DLL)也可以创建并使用单独的堆。
### 代码实现示例
以下是一个最小堆的C++实现:
```cpp
#pragma once
template
class MinHeap {
private:
T* _heap;
int _size;
int _capacity;
public:
MinHeap(int capacity) : _capacity(capacity), _size(0) {
_heap = new T[_capacity];
}
~MinHeap() {
delete[] _heap;
}
bool isEmpty() const {
return _size == 0;
}
bool isFull() const {
return _size == _capacity;
}
bool add(const T& value) {
if (isFull()) {
return false;
}
_heap[_size++] = value;
adjustUp(_size - 1);
return true;
}
void adjustDown(int index) {
int smallest = index;
int left = 2 * index + 1;
int right = 2 * index + 2;
if (left <_size && _heap[left] <_heap[smallest]) {
smallest = left;
}
if (right <_size && _heap[right] <_heap[smallest]) {
smallest = right;
}
if (smallest != index) {
std::swap(_heap[index], _heap[smallest]);
adjustDown(smallest);
}
}
void adjustUp(int index) {
while (index > 0 && _heap[(index - 1) / 2] > _heap[index]) {
std::swap(_heap[(index - 1) / 2], _heap[index]);
index = (index - 1) / 2;
}
}
};
```
此代码实现了最小堆的基本功能,包括插入和调整操作。
推荐阅读
-
蜡笔小新 2024-12-24 01:20:47
-
本文作者分享了在阿里巴巴获得实习offer的经历,包括五轮面试的详细内容和经验总结。其中四轮为技术面试,一轮为HR面试,涵盖了大量的Java技术和项目实践经验。 ...
[详细]
蜡笔小新 2024-12-23 11:32:02
-
-
本题探讨了在大数据结构背景下,如何通过整体二分和CDQ分治等高级算法优化处理复杂的时间序列问题。题目设定包括节点数量、查询次数和权重限制,并详细分析了解决方案中的关键步骤。 ...
[详细]
蜡笔小新 2024-12-22 19:34:39
-
本文系统梳理了机器学习的关键知识点,涵盖模型评估、正则化、线性模型、支持向量机、决策树及集成学习等内容,并深入探讨了各算法的原理和应用场景。 ...
[详细]
蜡笔小新 2024-12-22 09:15:30
-
本文旨在为读者提供对Java虚拟机(JVM)的全面理解,涵盖其主要组成部分、工作原理及其在不同平台上的实现。通过详细探讨JVM的结构和内部机制,帮助开发者更好地掌握Java编程的核心技术。 ...
[详细]
蜡笔小新 2024-12-21 23:50:40
-
在 Flutter 开发过程中,开发者经常会遇到 Widget 构造函数中的可选参数 Key。对于初学者来说,理解 Key 的作用和使用场景可能是一个挑战。本文将详细探讨 Key 的概念及其应用场景,并通过实例帮助你更好地掌握这一重要工具。 ...
[详细]
蜡笔小新 2024-12-25 08:05:15
-
本文详细探讨了Redis中的数据结构和对象系统的实现,包括字符串、列表、集合、哈希表和有序集合等五种核心对象类型,以及它们所使用的底层数据结构。通过分析源码和相关文献,帮助读者更好地理解Redis的设计原理。 ...
[详细]
蜡笔小新 2024-12-25 04:11:22
-
本文介绍了一种解决二元可满足性(2-SAT)问题的方法。通过具体实例,详细解释了如何构建模型、应用算法,并提供了编程实现的细节和优化建议。 ...
[详细]
蜡笔小新 2024-12-24 21:48:43
-
本文回顾了电路与系统的发展历程,从电的早期发现到现代电子器件的应用。文章不仅涵盖了基础理论和关键发明,还探讨了这一学科对计算机、人工智能及物联网等领域的深远影响。 ...
[详细]
蜡笔小新 2024-12-24 13:57:05
-
本文探讨了使用C#在SQL Server和Access数据库中批量插入多条数据的性能差异。通过具体代码示例,详细分析了两种数据库的执行效率,并提供了优化建议。 ...
[详细]
蜡笔小新 2024-12-23 13:03:32
-
对象自省自省在计算机编程领域里,是指在运行时判断一个对象的类型和能力。dir能够返回一个列表,列举了一个对象所拥有的属性和方法。my_list[ ...
[详细]
蜡笔小新 2024-12-23 12:55:35
-
本文通过使用2013-14赛季NBA赛程与结果数据集以及2013年NBA排名数据,结合《Python数据挖掘入门与实践》一书中的方法,展示如何应用决策树算法进行比赛胜负预测。我们将详细讲解数据预处理、特征工程及模型评估等关键步骤。 ...
[详细]
蜡笔小新 2024-12-23 09:07:40
-
本文介绍 SQL Server 的基本概念和操作,涵盖系统数据库、常用数据类型、表的创建及增删改查等基础操作。通过实例帮助读者快速上手 SQL Server 数据库管理。 ...
[详细]
蜡笔小新 2024-12-22 18:39:17
-
本文总结了2018-2019学年第六周在《Java数据结构与算法》课程中的学习内容,重点介绍了非线性数据结构——树的相关知识及其应用。 ...
[详细]
蜡笔小新 2024-12-22 16:43:19
-
本题来自WC2014,题目编号为BZOJ3435、洛谷P3920和UOJ55。该问题描述了一棵不断生长的带权树及其节点上小精灵之间的友谊关系,要求实时计算每次新增节点后树上所有可能的朋友对数。 ...
[详细]
蜡笔小新 2024-12-22 14:36:54
-