堆(Heap)是满足堆序性质的完全二叉树:大根堆父 $\geq$ 子(根最大);小根堆父 $\leq$ 子(根最小)。
堆用数组顺序存储:$i$ 的左孩子 $2i$、右孩子 $2i+1$、父节点 $\lfloor i/2 \rfloor$(下标从 1 开始,0 号位常作暂存)。
从最后一个非叶节点 $\lfloor n/2 \rfloor$ 开始,向前依次对每个节点执行下滤(sift down)到根。
void BuildMaxHeap(int A[], int n){
for (int i = n/2; i >= 1; i--)
AdjustDown(A, i, n);
}
void AdjustDown(int A[], int k, int n){
A[0] = A[k]; // 暂存
for (int i = 2*k; i <= n; i *= 2){
if (i < n && A[i] < A[i+1]) i++; // 选较大的子节点
if (A[0] >= A[i]) break;
A[k] = A[i]; k = i; // 大孩子上移,继续下滤
}
A[k] = A[0];
}
新元素放到数组末尾,与父节点比较,若大于父节点则交换(上滤 / sift up),直到满足堆序。O(log n)。
堆顶与末尾元素交换,堆大小减 1,再对新的堆顶执行下滤。O(log n)。
| 性质 | 说明 |
|---|---|
| 存储结构 | 完全二叉树,用数组存储 |
| 堆序性 | 大根堆 $A[\text{parent}] \geq A[\text{child}]$ |
| 建堆复杂度 | O(n),不是 O(n log n) |
| 插入 / 删除堆顶 | O(log n)(上滤 / 下滤最多到根或叶) |
| 取堆顶 | O(1) |
| 堆排序 | O(n log n),不稳定 |
| 考法 | 解题套路 |
|---|---|
| 手动建堆 | 从 $\lfloor n/2 \rfloor$ 开始逐个下滤 |
| 堆插入 / 删除 | 插入→上滤;删除→末尾替换 + 下滤 |
| 建堆时间复杂度 | O(n) 不是 O(n log n),用级数求和证明 |
| 堆与排序 | 堆排序 = 反复取堆顶 + 下滤,O(n log n) |
| 判断是否为堆 | 检查每个父节点与子节点的关系 |
↑ 以上为站内 HTML 相对链接(纯网页可浏览);本页右上「在 Obsidian 中打开」跳回源笔记。