Skip to content

2025-07-30-优先级队列

概念

  1. 它是由完全二叉树构成的树,底层是用线性表来存储
  2. 它分为大根堆与小根堆
    • 大根堆:树中所有的根节点都要比子节点大
    • 小根堆:树中所有的根节点都要比子节点小

模拟实现

初始化

就以大根堆为例

前置知识:

  1. 二叉树父节点与子节点位置的关系
  2. useSize 用来表示使用个数
  3. 结束条件:当 child >= useSize(此时下标无效,也就结束了) 或者 elems[father] >= elems[child] 的时候

步骤:

  1. 通过 (useSize - 1 - 1) / 2 获取到 parent
  2. 使用 siftDown() 这个方法,向下调整
    • 先获取到 child 下标
    • 进入循环,循环结束条件就是 child >= useSize
    • 在循环内,先获取到最大的孩子节点的下标(注意下标合法性),然后交换,如果不需要交换,那么就直接退出

问题:它的时间复杂度是多少呢?

解析:

  • 背景:以满二叉树为例,根节点在第 1 层,总层数为 H

  • 步骤:

  • Java-优先级队列-模拟实现-初始化-向下转型的时间复杂度
    Java-优先级队列-模拟实现-初始化-向下转型的时间复杂度
    1. 由这幅图可以看出,第 k 层节点个数为 2k1,每个节点最多执行的次数是 Hk

    2. 所以得出执行的个数

      O(N)=211×(H1)+221×(H2)+231×(H3)++2H21×2+2H11×1
    3. 利用错位相减法,先把 O(N)×2 然后相减得出 O(N)

      1. O(N) 的原始公式记为 ①,将其左右两边同乘 2 记为 ②:

        O(N)=20(H1)+21(H2)+22(H3)++2H2(1)--- ①2×O(N)=21(H1)+22(H2)++2H2(2)+2H1(1)--- ②
      2. 使用 ②式 减去 ①式 进行错位相减(将底数相同的项对齐相减):

        2O(N)O(N)=20(H1)+21(1)+22(1)++2H2(1)+2H1(1)O(N)=1H+21+22+23++2H1
    4. 后面部分是一个标准的等比数列求和。根据等比数列求和公式 Sn=a1(1qn)1q 计算:

      O(N)=1H+2(12H1)12O(N)=1H+2H2O(N)=2HH1
    5. 最后,利用二叉树的性质,我们将树的高度 H 替换为节点个数 N

      O(N)=(N+1)log2(N+1)1O(N)=Nlog2(N+1)

    结论: 在大 O 渐进表示法中,保留最高阶项,忽略对数项,因此向下调整建堆的时间复杂度为 O(N)

增删查排序

增加

利用向上调整,添加元素,如果初始化的元素都用 offer() 这个方法, 那么时间复杂度为 O(N)

删除+查询

删除的是利用向下调整,先将首尾相换,然后 useSize--,最后向下调整

排序

只需要每次首尾交换,然后调用 siftDown() 即可