Java PriorityQueue默认是最小堆,底层用Object[]数组实现,通过siftUp和siftDown维护堆序:插入时从末尾上浮,删除时用末尾元素填补后下沉,索引关系为父节点(i-1)/2、左子2i+1、右子2i+2。

Java 的 PriorityQueue 默认是最小堆,底层用动态数组(Object[] queue)实现。它不直接暴露上浮/下沉逻辑,但内部通过 siftUp 和 siftDown 严格维护堆序:新元素插入末尾后上浮,删除堆顶后用末尾元素填补再下沉。
插入时调用 siftUp 维持最小堆序
插入元素时,先加到数组末尾(索引 k),然后不断与父节点比较,若更小就交换,直到满足 queue[k] ≥ queue[parent(k)]。
父节点索引为 (k - 1) / 2(整除),上浮过程如下:
- 设当前索引
k,父索引parent = (k - 1) >> 1 - 若
queue[k].compareTo(queue[parent]) ,交换两者 - 令
k = parent,重复直到k == 0或不再小于父节点
删除堆顶时调用 siftDown 恢复堆结构
移除堆顶(索引 0)后,把末尾元素移到索引 0,再向下调整:和两个子节点中较小者比较,若大于它就交换,持续下沉到底层。
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
关键细节:
- 左子索引
child = k * 2 + 1,右子索引child + 1 - 先找出
child和child + 1中较小的节点(存在前提下) - 若
queue[k] > queue[smallestChild],交换并令k = smallestChild,继续下沉 - 终止条件:无子节点,或
queue[k]已不大于任一子节点
数组索引关系是上浮/下沉的数学基础
完全二叉树用数组表示时,索引从 0 开始,父子/左右子关系固定:
- 节点
i的父节点:(i - 1) / 2 - 节点
i的左子节点:2 * i + 1 - 节点
i的右子节点:2 * i + 2
这些整数运算保证了无需指针、仅靠下标就能定位关联节点,是 siftUp 和 siftDown 正确性的根本。
注意:siftDown 在 removeAt 中也用于任意位置删除
PriorityQueue 的 remove(Object) 会先遍历找索引,再调用私有方法 siftDown(int i):把末尾元素填入 i 位置,然后向下调整;若该元素比父节点还小,再额外调用 siftUp(i) 向上修复。
这说明:单次操作可能触发双向调整,但最终仍只依赖同一套索引规则和比较逻辑来维持最小堆性质。

















