优先级队列底层用堆实现,核心是通过向上调整(插入后上浮)和向下调整(删除后下沉)动态维护堆序性;建堆采用从最后一个非叶子节点逆序向下调整,时间复杂度O(N);权重映射需据业务选择大根堆或小根堆,并预处理数值。

优先级队列底层靠堆实现,而堆的“权重排序”本质不是直接比权重值,而是通过向上调整(插入时)和向下调整(删除或建堆时)动态维护父子节点间的大小关系。关键不在“存什么”,而在“怎么调”。
向上调整:新元素插入后的自修复
插入总在数组末尾,但新元素可能破坏堆序性。此时需让它“逐层上浮”直到满足条件:
- 从当前下标 child 开始,算出父节点 parent = (child − 1) / 2
- 若为大根堆且 a[child] > a[parent],则交换,并把 parent 当作新的 child 继续上浮
- 循环终止条件是 child == 0(已到根)或不再满足上浮条件
- 注意:前提必须是插入前其余部分已是合法堆,否则上浮无法收敛
向下调整:堆顶变动后的稳态重建
删除堆顶(最大/最小元)后,通常用末尾元素补空位,再让它“沉到底部合适位置”:
- 从根(parent = 0)出发,先定位左右子中更符合堆序的那个孩子(大根堆选较大者,小根堆选较小者)
- 比较该孩子与父节点:若孩子更“优”(如大根堆中孩子更大),则交换;否则停止
- 交换后,以该孩子位置为新 parent,重复上述过程
- 必须始终检查子节点索引是否越界(left = 2×parent + 1 ),否则访问非法内存
建堆:批量数据的高效初始化
给定无序数组,不能逐个插入(O(N log N)),而应从最后一个非叶子节点开始逆序向下调整:
- 最后一个非叶子节点索引是 (n / 2) − 1(因叶子节点从 ⌊n/2⌋ 起)
- 对每个 i 从 (n/2)−1 到 0 执行 AdjustDown(a, n, i)
- 此法时间复杂度为 O(N),远优于反复插入
- 错误做法:从根开始顺向调整——子树尚未有序,父节点调整后立即又被子树打破
权重映射与堆类型选择
优先级队列中的“权重”常为业务字段(如任务截止时间、用户等级),需提前转为可比数值:
- 若要高权重优先出队(如紧急任务先处理),用大根堆,权重值直接入堆
- 若要低权重优先(如按耗时升序调度),用小根堆,或对原始权重取负再入大根堆
- 结构体入堆时,切勿直接比较地址或指针,应在 AdjustUp/Down 中提取并比较权重字段
- 避免在调整函数里做复杂计算(如实时调用函数获取权重),应预处理好数值数组

















