半路算法之二项树与二项堆

半路算法之二项树与二项堆

秉承前文。前面提到过针对稀疏图时,以二项堆来作为最小优先队列是更为适宜的。这里记录一下学习二项堆的过程。

二项堆的名字来源于二项树。二项堆是多个二项树连在了一起。
二项树的名字来源于其 Bn 棵树的元素个数为 2n ,且其深度n处恰有 2k 个节点,其性质与二项式非常吻合。此外,它还是一种递归定义的有序树。
重点依照二项式的性质说一下二项树的性质:

首先二项式定理的公式表示为:

(a+b)n=r=0ncrnanrbr

嗯,在二项树中我们将上式的a和b统统定位1。
那么二项树的第一个性质—— 共有 2k 个节点,便可以理解为上面二项式的值了;
我们假设 树的高度为r(即画出来的树有r行),在 其深度n处有 Ckn 个节点,其中i=0, 1, 2, …, k,理解为其二项式系数,嗯,刚好等于 Ckn
我们假设 根节点(这一行只有它自己,它没有兄弟姐妹节点)的度数为r,它 的度数是这棵二项树上最大的,而且其子女节点分别是它们(子女节点)相对应的子树的根(真有点拗口)

这些性质的证明基本就是二项式定理的证明(数学归纳法,亦即递归)了。这里不再展开。
依据性质1和3,我们知道如果一棵二项树的总结点数为n,那么其节点的最大度数为lgn。

接下来看二项堆。二项堆就是一些二项树把根节点连了起来。它和下一次要讨论的斐波那契堆称为可合并堆,它们支持以下五种操作:

make-heap()     --创建并返回一个不包含任何元素的新堆
insert(H, x)        --将节点x(有值)插入到堆H中
minimum(H)      --返回一个指向堆H中包含最小关键字的节点的指针
extract-min(H)  --将堆H中包含最小关键字的节点删除并返回指向该节点的指针
union(H1, H2)       --创建并返回一个包含堆H1和H2中所有节点的新堆,同时删除堆H1和H2

二项堆中的每个二项树遵循最小堆的性质,其节点的关键字(即节点的值)大于或等于其父节点的关键字。由于二项堆是有二项树拼起来的,其性质完全就是二项树的那些,不再进一步讨论了。

这里重点说说二项堆的函数实现:

新建一个二项堆
嗯,就是分配并返回了一个对象H,且head[H]=NULL,运行时间为O(1)

寻找最小关键字

伪代码
binomial-heap-minimum(H)

y <- NULL
x <- head[H]
min <- ∞
while x≠NULL
    do if key[x]<min
        then min <- key[x]
            y <- x

        x <- sibling[x]
return y

我们需要注意的是关键字只在二项树内排序
代码实现为:

while (x != NULL)
{
    if (x.key < min)
    {
        min = x.key;
        y = x;
        x = x.sibling;
    }
}
return y;

合并两个二项堆

伪代码
binomial-link(y, z)

p[y] <- z
sibling[y] <- child[z]
child[z] <- y
degree[z] <- degree[z]+1

代码实现为:

y.parent = z.child;
z.child = y;
z.degree++;

后面还有合并、插入、取得最小值、去掉最小值、删除某个值的操作。下一篇再写。
另:本篇公式采用MathJax引擎进行了latex公式编写,脚本为:

顺便推荐一下一篇很好的带有常用写法的latex介绍:
一份不太简短的 LATEX 2ε 介绍
星期六, 15. 四月 2017 10:37下午

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值