二叉堆用数组实现优先级队列,通过索引算术映射完全二叉树,核心是上浮(swim)和下沉(sink)操作,使插入和删除均达o(log n);相比链表或有序数组更均衡适配动态增删场景。
用二叉堆手写优先级队列,核心是把“完全二叉树”映射到数组里,靠父子索引关系维护堆序,而不是真建树节点。关键不在代码多,而在理解两个动作:新元素插入后上浮(swim)、取最大/最小值后下沉(sink)。只要这两个逻辑写对,其余就是封装和边界处理。
为什么选二叉堆而不是链表或普通数组
链表入队快但找最大值要遍历 O(n);有序数组出队快但每次插入都要挪动元素 O(n);而二叉堆让入队和出队都稳定在 O(log n) —— 这是动态场景下最均衡的选择。比如任务调度、实时消息分发,元素不断来又不断走,堆结构刚好应对这种“边增边删”的节奏。
数组怎么表示一棵完全二叉树
不用指针,直接用一维数组,约定索引从 1 开始(第 0 位空着),就能靠算术快速定位父子关系:
- 节点 i 的父节点索引是 i // 2
- 节点 i 的左子节点索引是 2 * i
- 节点 i 的右子节点索引是 2 * i + 1
这个设计让树的层序遍历天然对应数组顺序,既省空间又免指针跳转。注意:不是所有语言默认支持索引 0 空着,Java 或 C++ 实现时可统一偏移 1,Python 列表则直接在开头 append 一个占位符。
关键操作:上浮与下沉怎么写
以最大堆为例(高优先级 = 值大):
- 上浮(insert 后调用):新元素加在数组末尾,然后不断和父节点比较;若比父大,就交换,继续往上;直到不比父大或到达根节点。
- 下沉(delMax 后调用):先把堆尾元素提到堆顶,再让它和两个子节点中较大的那个比较;若比它小,就交换下去;重复直到它大于等于两个子节点,或已无子节点。
下沉时要注意:必须先判断左右子是否存在(索引是否越界),再比大小;否则可能访问空位置导致异常。下沉和上浮都是沿着单条路径走,最多 log₂n 步,所以时间可控。
完整骨架与注意事项
一个最小可用版本包含这些方法:init(初始化空数组+size计数器)、insert(append + swim)、delMin/delMax(取头、换尾、sink)、peek(只看不删)。别忘了扩容逻辑——当数组满时,按 1.5 倍或 2 倍扩,并复制旧数据。另外,如果语言不支持泛型比较(如 Python 的 __lt__),需显式传入比较函数或要求元素实现 Comparable 接口。











