方案一:自上而下的上滤
时间复杂度:
$\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)$
插入的平均时间复杂度为 $O(1)$
习题解析[10-6]:
若一个新节点 $p$ 上升 k 层,则其到达的位置的子树有 $2^{k+1} - 1$ 个节点,再算上父节点,共 $2^{k+1}$ 个。$p$ 要在这些节点中当次大者,或者说次大者刚好是 $p$ ,即 $P(k) = (1/2)^{k+1} = (1/2)^{k} \cdot (1/2)$ ,这是几何分布,所以期望为 $1$ 。插入后节点平均上升 $1$ 层。
但是,删除的平均时间复杂度还是为 $O(logn)$
因为删除的节点是最末尾上去的,本身其就偏小,下滤层数偏高,平均要 $O(logn)$ 应该没问题。
所有元素相等,这种最好情况下,完全二叉堆删除的最好时间复杂度为 $O(1)$
大根堆无法支持高效地getMin()
,因为其要比较所有叶子才知道最小值。
min-max heap,能同时支持 O(1) 时间 getMin 和 getMax,插入和删除的时间复杂度为 O(logn)
min-max heap 逻辑结构也是个完全二叉树,满足两条性质:
If X is on a min level, then X.key is the minimum key among all keys in the subtree with root X
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子树已满足序
如果 key 在 max 层
如果 key <= parent,那么交换,调整随即完毕,其它位置也没问题
如果 key > parent,虽然 key 和 parent 不用换,但此时可能由于 key 过大破坏 grandparent 的max堆序性质,grandparent层 要和 key层 当作大根堆调整。 此时若 key <= grandparent,调整完毕;若 key > grandparent,交换二者,操作位置上升两层(交换下来的 grandparent,其关心下两层,自己够大没问题;其被上两层关心,其上一层够小,上上层够大,也没问题)。
如果parent在max层
对称情况
删除时的下滤:
如果 key 在 max 层
key下面的两层是个有序向量的两头(但其有宽度),那么key就有5类位置情况!
但是实际却没那么复杂:
key 若比子孙二层都大,力所能任,调整完毕
key 不够大,那选子孙中的最大者来替代自己,key跑到了替代者的位置上
若 key 跑到了中间的 min 层,说明这个位置没后代,调整完毕
若 key 跑到了 grandson 层,其需要考虑与其父的大小关系,如果 key 更小还需要与其父交换下。不论如何,调整位置下降两层。
如果 key 在 min 层
对称情况
大概是这样,没详细看原链接,大概想了下调整的逻辑应该是这样,可能有问题,就这样吧。