1. 堆数据结构基础解析
堆是一种特殊的完全二叉树结构,在计算机科学中有着广泛的应用。完全二叉树的特点是除了最后一层外,其他层的节点都是满的,且最后一层的节点都集中在左侧。这种结构特性使得我们可以用简单的数组来高效地表示和操作堆。
1.1 堆的核心特性
堆分为两种基本类型:大根堆和小根堆。大根堆中,每个节点的值都大于或等于其子节点的值;小根堆则相反,每个节点的值都小于或等于其子节点的值。这种特性保证了堆顶元素总是整个堆中的最大值(大根堆)或最小值(小根堆)。
堆的这种特性使其非常适合需要频繁访问最大或最小元素的场景,比如优先级队列的实现、堆排序算法等。在实际应用中,堆经常用于任务调度、图算法(如Dijkstra最短路径算法)、数据流的中位数查找等问题。
1.2 堆的数组表示
由于堆是完全二叉树,我们可以用数组来高效地存储它。这种表示方法节省了指针存储空间,且访问效率高。数组表示法中:
- 根节点存储在索引1的位置(有些实现使用0作为根节点,但使用1可以简化计算)
- 对于任意节点i,其左子节点位于2i,右子节点位于2i+1
- 父节点位置为i/2(整数除法)
这种表示法的优势在于:
- 不需要额外的指针存储空间
- 通过简单的算术运算即可快速定位父子节点
- 缓存友好,因为数组元素在内存中是连续存储的
注意:在实际编程中,数组索引从0开始还是1开始会影响父子节点的计算方式。本文示例采用从1开始的方式,因为这样计算更直观(父节点=i/2)。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 堆的核心操作算法
堆的核心操作包括向上调整(up)和向下调整(down)算法,它们是构建堆所有其他操作的基础。
2.1 向上调整算法
向上调整算法用于在堆中插入新元素时维护堆的性质。当新元素被添加到堆的末尾后,需要通过向上调整使其到达正确的位置。
算法步骤如下:
- 将新元素放在堆的最后一个位置
- 比较该元素与其父节点的值
- 如果违反堆序性质(大根堆中子节点大于父节点,或小根堆中子节点小于父节点),则交换两者
- 重复这个过程,直到满足堆序性质或到达根节点
cpp复制void up(int child) {
int parent = child / 2;
while(parent >= 1 && heap[child] > heap[parent]) {
swap(heap[child], heap[parent]);
child = parent;
parent = child / 2;
}
}
这个算法的时间复杂度是O(log n),因为最坏情况下需要从叶子节点移动到根节点,而完全二叉树的高度是log n。
2.2 向下调整算法
向下调整算法通常用于删除堆顶元素后维护堆的性质。当堆顶元素被移除后,我们将最后一个元素移到堆顶,然后通过向下调整使其下沉到合适的位置。
算法步骤如下:
- 从根节点开始,比较父节点与两个子节点的值
- 找出值更大(大根堆)或更小(小根堆)的子节点
- 如果父节点不满足堆序性质,则
