左式堆

Posted exhina

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了左式堆相关的知识,希望对你有一定的参考价值。

1. 堆合并

两个完全二叉堆的合并算法:

1.1 A.insert( B.del_max() )

完全二叉堆是基于vector实现的,故若采用合并算法,只需将堆A(n)作为一个基本堆,进而不断的将堆B(m)的元素进行删除取出,重新插入A中。

每次迭代为一次删除和一次插入操作,共进行m次迭代。

复杂度为 m * { O(logm)+ O(log(n + m)) } — O(mlogn)

1.2 Floyd建堆算法

将两个堆的元素任意混合为一个新的向量,只需O(min(n,m))时间,再调用建堆算法,其复杂度为O(n + m)

以上两种算法的复杂度都不尽人意,没有考虑两个堆已经是偏序的堆

2. 空节点路径长度

在二叉搜索树中,在逻辑上定义内部节点和外部节点,外部节点为度为0/1节点的孩子,从而实现建立一棵度均为偶数的树

Null Path Length — npl(x)

1)      当前节点为外部节点npl(x) = 0

2)      当前节点为内部节点,npl(x) = 1 + min( npl(lc), npl(lc) ),左右孩子中空节点长度的最小值加1

3)      npl(x) = x到外部节点的最短路径

4)      也是以x为根的最大满子树的树高

3. 左倾性

要满足左倾性,内部节点x的左孩子的npl不小于右孩子的npl

npl(x->lc)  >= npl(x->rc) 由此可知,npl(x) = 1 + npl(x->rc)

但是并不意味着左孩子的规模和高度也大于其右孩子

 

4. 右侧链

从x出发,一直沿着其右侧孩子路径出发,到达外部节点时,其路径为右侧链rPath(x),显然由于npl(x) = 1 + npl(x->rc),每个节点的npl值都是由右侧子孙决定的。

根节点的右侧通路的终点必然是全堆深度最小的外部节点,由此构成一棵以r为根,d为rPath(root)的满二叉树。

计算可知,其右侧链长度不过O(logn)

5. 左式堆

左式堆是优先级队列的另外实现形式,能够在O(logn)的复杂度实现两堆的合并,其需要调整的节点数只在O(logn)下实现。

5.1 左式堆的合并

合并A堆和B堆,只需将A堆的右子堆与B堆进行合并,从而递归的实现

设置A>=B

Merge(A,B)

其细节在于:

1. 每次调整前需比较A,B的大小,始终保持A>=B,进行交换即可

2. 合并完成后,需要更新A的右子堆子父关系A->rc->parent = A

3. 更为重要的是,需要比较A的新右子堆和左子堆的npl关系,保证左孩子的npl不小于右孩子npl,为此进行交换即可

 

以上是关于左式堆的主要内容,如果未能解决你的问题,请参考以下文章

转载:数据结构 左式堆

堆之左式堆和斜堆

数据结构--左式堆的思想和代码

左式堆实现

左式堆的合并

左式堆