“小规模可以完全算清:$n=3$ 时 $\lceil\log 2 6\rceil=3$,故任何比较排序最坏至少 $3$ 次比较;插入排序恰以最坏 $3$ 次完成三元素排序,说明该下界在小规模处…”
形式陈述
二叉最小堆是一棵满足形状与堆序不变量的二叉树,也允许用空树表示空堆。非空时,除最末层外各层填满,最末层从左连续填入,形成完全二叉树。键取自一个全序空间,每个父键不大于其孩子的键;沿根到任一节点的路径传递,便知根键最小。兄弟节点或不同子树之间无须有序。
完全形状使堆可用数组隐式存储。下标从
这些修复各走一条高度为
自底向上建堆
Floyd 法按下标从
下沉的工作与节点高度成正比,再加每个处理节点的常数开销。完全二叉树中,高度至少为
因此建堆总时间为
直觉
若目标只是反复取出最小元,维护完整排序纯属浪费:排序确定所有元素对的相对次序,而我们每次只需要知道“谁最小”。堆的设计哲学是维护恰好够用的最少秩序——只约束父子、不约束兄弟,全局最小自动浮到顶端,其余次序悬而不决、按需再定。完全二叉树的形状则同时买到两件事:高度恰为
下图采用从
例子与边界
数组
堆只保存父子之间的次序。查找任意给定键时,最坏需要检查
反复插入与自底向上建堆有不同成本。按递减序把互异键插入最小堆,每个新键都会上浮到根,总成本为
把全部比较方向反转,就得到对称的最大堆。二叉搜索树使用另一种不变量,约束整棵左、右子树的键范围;它的导航规则不适用于只维护父子堆序的结构。
推论与应用
二叉堆是优先队列 ADT的一种实现,而非该接口本身:在上述无搬迁的数组 RAM 模型中,它给出最坏 find-min、最坏 insert、delete-min 与已定位元素的 decrease-key。若底层使用几何扩容并以适当滞回阈值缩容,则更新仍为摊还 meld 需要
它直接服务于 Dijkstra 算法与 Prim 算法的“取当前最小候选”主循环、Huffman 编码的反复合并最小权对,以及事件驱动模拟与任务调度。Fibonacci 堆用更复杂的延迟整理换取摊还 insert、meld 与 decrease-key,但 delete-min 仍为摊还
参考资料
-
Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and Clifford Stein, Introduction to Algorithms, 4th ed., MIT Press, 2022,Ch. 6, heaps, priority queues, and linear-time build。
-
Robert Sedgewick and Kevin Wayne, Algorithms, 4th ed., Addison-Wesley, 2011,§2.4, priority queues and heaps。
-
Robert Sedgewick、Kevin Wayne,Algorithms, 4th ed., Addison-Wesley, 2011,MinPQ 实现契约:明确将动态数组搬迁计入更新的摊还界。