Java中PriorityQueue默认基于二叉小顶堆实现,底层用数组模拟完全二叉树,通过下标关系(左=2i+1、右=2i+2、父=(i-1)/2)维护堆序,支持O(log n)插入(siftUp)和删除(siftDown),并可通过Comparator自定义排序规则。

Java 中的 PriorityQueue 默认就是基于**二叉小顶堆(min-heap)**实现的,它不直接暴露底层结构,但内部用数组模拟完全二叉树,通过父子节点下标关系维护堆序性。
小顶堆的存储结构:数组模拟完全二叉树
PriorityQueue 底层是一个动态扩容的 Object 数组(queue),索引从 0 开始。对于任意节点索引 i:
- 左孩子索引 =
2 * i + 1 - 右孩子索引 =
2 * i + 2 - 父节点索引 =
(i - 1) / 2(整除)
这种映射保证了树的“完全二叉”形态,也使得插入、删除能在 O(log n) 时间内完成。
插入元素:上浮(siftUp)维持小顶堆性质
调用 offer() 或 add() 时,新元素先放在数组末尾,然后不断与父节点比较:若比父小,就交换位置,直到满足“父 ≤ 子”。
立即学习“Java免费学习笔记(深入)”;
例如插入 3、1、4、1(重复允许):
- 插 3 → [3]
- 插 1 → [3,1] → 上浮:1 比 3 小 → 交换 → [1,3]
- 插 4 → [1,3,4](已满足堆序)
- 插 1 → [1,3,4,1] → 上浮:1 比父(3)小 → 交换 → [1,1,4,3]
获取/弹出最小值:下沉(siftDown)恢复堆结构
poll() 总是返回并移除堆顶(即数组第一个元素),然后把最后一个元素移到堆顶,再向下调整:
- 比较当前节点与两个子节点中的较小者
- 若当前节点大于该较小值,则交换;继续下沉,直到不再违反小顶堆性质
比如从 [1,1,4,3] 中 poll():
- 返回 1,剩余 [3,1,4](先挪末尾 3 到堆顶)
- 3 比左右子(1 和 4)都大 → 与左子 1 交换 → [1,3,4]
- 此时已满足堆序
自定义排序:传入 Comparator 构造小顶堆或大顶堆
默认构造器使用元素自然顺序(要求实现 Comparable),也可传入 Comparator 改变比较逻辑:
- 小顶堆(升序):
new PriorityQueue(Comparator.naturalOrder()) - 大顶堆(降序):
new PriorityQueue(Comparator.reverseOrder()) - 按字符串长度小顶堆:
new PriorityQueue((a, b) -> a.length() - b.length())
注意:Comparator 定义的是“谁优先”,不是“是否交换”。只要保证 compare(a,b) 表示 a 应排在 b 前面(即 a 优先级更高),PriorityQueue 就会把它放在更靠近堆顶的位置。


















