cs

完全二叉堆

堆化Heapify

方案一:自上而下的上滤

时间复杂度:

$\sum \limits_{i=0}^{h}i \cdot 2^i = O(nlogn)$

类似元素逐渐插入的处理过程。

方案二:自下而上的下滤

时间复杂度:

$\sum \limits_{i=0}^{h}(h-i) \cdot 2^i = O(n)$

所以,堆化时要自下而上的下滤for (int i = n / 2 - 1; i != -1; i--) percolateDown(),$n/2 - 1$ 的边界是:最后一个有孩子的节点 $x$ 满足:$2x + 1 \le n - 1$,即 $x \le n / 2 - 1$,即 $x \le \lfloor n / 2 \rfloor - 1$

自下而上的下滤时间复杂度更低的原因在于,完全二叉树靠下方的节点多,它们往下走步数少,让这占比最多的节点往下走,整体走的步数少。

为什么没有对称的两种情况,即自上而下的下滤,自下而上的上滤。

以自下而上上滤为例,大根堆,假如一次上滤把一个极小的值换下来了,其没有继续向下的机会。一个例子如:

    1
   / \
  2   0
 /
3

3上滤之后,2变到最下面,但是2后面是上不去的。

再考虑为什么自上而下的上滤、自下而上的下滤能得到正确的堆序,以前者为例。自上而下处理的过程中,上方部分是处理过的,保持了堆序,然后偏右下位置的新元素利用已有的堆序操作,并继续维持,到最后能保证整个向量的堆序性。自下而上的下滤也是同理。

所以,自上而下必须上滤,自下而上必须下滤,才能得到正确的堆序。

插入和删除的平均时间复杂度

最坏都是 $O(logn)$

min-max 堆

大根堆无法支持高效地getMin(),因为其要比较所有叶子才知道最小值。

min-max heap,能同时支持 O(1) 时间 getMin 和 getMax,插入和删除的时间复杂度为 O(logn)

min-max heap 逻辑结构也是个完全二叉树,满足两条性质:

  1. If X is on a min level, then X.key is the minimum key among all keys in the subtree with root X

  2. If X is on a max level, then X.key is the maximum key among all keys in the subtree with root X

每层呈现 min-max-min-max 的结构,注意由于值分层交替,这里的堆序要定义为:一个节点 >= / <= 其所有后代,仅仅是左右孩子不足以确定一个节点与后代的关系

维护这两个性质即可知道根为最大值,根 / 根的两个儿子之一为最小值

可以看到相邻的两层实际是一个有序向量的两头

如何维护一个max / min层点?

以max点为例,其后代中的次大者为其(最多4个)grandson,然后其还要保证>=儿子层。所以,一个点最多只会关心两层的变化,即其儿子层和孙子层,一个点的变化也只被其父亲层和祖父层关心

以一个max层点为例,其被别人关心时,别人关心它是否够大 / 过大;其关心别人时,关心自己是否够大。

插入时的上滤:

此时key子树已满足序

  1. 如果 key 在 max 层

    • 如果 key <= parent,那么交换,调整随即完毕,其它位置也没问题

    • 如果 key > parent,虽然 key 和 parent 不用换,但此时可能由于 key 过大破坏 grandparent 的max堆序性质,grandparent层 要和 key层 当作大根堆调整。 此时若 key <= grandparent,调整完毕;若 key > grandparent,交换二者,操作位置上升两层(交换下来的 grandparent,其关心下两层,自己够大没问题;其被上两层关心,其上一层够小,上上层够大,也没问题)。

  2. 如果parent在max层

    对称情况

删除时的下滤:

  1. 如果 key 在 max 层

    key下面的两层是个有序向量的两头(但其有宽度),那么key就有5类位置情况!

    但是实际却没那么复杂:

    • key 若比子孙二层都大,力所能任,调整完毕

    • key 不够大,那选子孙中的最大者来替代自己,key跑到了替代者的位置上

      • 若 key 跑到了中间的 min 层,说明这个位置没后代,调整完毕

      • 若 key 跑到了 grandson 层,其需要考虑与其父的大小关系,如果 key 更小还需要与其父交换下。不论如何,调整位置下降两层。

  2. 如果 key 在 min 层

    对称情况

大概是这样,没详细看原链接,大概想了下调整的逻辑应该是这样,可能有问题,就这样吧。