优先队列让你总能 O(log n) 拿到当前最小值。最常见的实现是二叉堆——一棵”父节点不大于子节点”的完全二叉树,正好可以用一个数组紧凑存储。
数组与树的关系
节点 i 的:
- 父节点:
(i - 1) >> 1 - 左子:
2i + 1 - 右子:
2i + 2
数组就是树的”层序遍历”。这就是为什么动画里数组的方块和树里的节点是同一个元素——它们是同一份数据的两种表示。
两个核心操作
insert(v):把 v 加到数组末尾(树的最后一个叶子位置),然后上浮:只要比父小就交换,直到父更小或自己成为根。
extractMin():根就是最小值。把它取出后,把数组末尾元素挪到根,然后下沉:与两个孩子中较小的比较,逆序就交换,直到不再违反堆性质。
每次操作最多走树的高度,约 ⌈log₂ n⌉ 步。
复杂度
- insert / extractMin:O(log n)
- peek:O(1)
- 空间:O(n)
试试看
可视化上方有输入框:随便输个数字按”插入”,看上浮过程;按”弹出最小值”看下沉过程。整个操作序列每次变化都会从头重放,方便你来回比对。
在动画里看什么
- 蓝色:正在比较的父子对(同时高亮连线)
- 红色:发生交换的两个节点
- 紫色:当前焦点(刚插入或刚成为新根)
- 数组与树两个视图里的同一个值是同一个元素——交换发生时两边同步变化