斐波那契堆

今天看斐波那契堆看的头昏脑胀,原因是书上写的太乱了。。。

看到网友写的就很不错

http://mindlee.net/2011/09/29/fibonacci-heaps/


由于增加了删除和关键字减值操作,所以,F堆中的最小树就不一定必须是二项树了。事实上,可能存在度为k却只有k + 1(原书是k + 1,应该是k – 1吧)个结点的最小树。为了保证每个度为k的最小树至少包含ck个结点(c > 1), 每次执行删除操作和关键字减值操作后,还必须进行级联剪枝操作。为此,为每个结点增加一个布尔类型的child_cut域(即本文里的marked)。child_cut域的值仅对那些不是最小树树根的结点有意义。对于不是最小树树根的结点x, x的child_cut域为TRUE,当且仅当在最近一次x成为其当前父结点的儿子之后,x的一个儿子被删除。这就意味着,在执行删除最小元素中,每次连接两棵最小树时,关键字值较大的根结点的child_cut域应该赋值为FALSE。更进一步地说,一旦删除操作或关键字减值操作将最小树的非根结点q从其所在双向链表中删除时,则调用级联剪枝操作。在执行级联剪枝操作过程中,检查从被删除结点q的父节点p开始,到被删节点的最近的child_cut域为FALSE的祖先结点的路径。对在该路径上所有child_cut域为TRUE的非根结点,将其从所在的双向链表中删除,并将其加入到F堆的最小树的根节点组成的双向链表中。如果该路径上存在child_cut域为FALSE的结点 ,则将其该域的值修改为TRUE。


 级联剪切的过程很明了,我当时看的时候最烦的问题是,为什么要进行级联剪切,级联剪切丫的要干什么? 

     如果仅仅要切除父结点y的一个结点x,则仅仅需要把结点x加入到根结点所在双向链表中,再检测y是否marked == true即可,这是因为斐波那契中的树并不一定是二项树,近似二项树也可以。当删除y的第二个结点时,对在该路径上所有marked域为TRUE的非根结点,将其从所在的双向链表中删除,并将其加入到F堆的最小树的根节点组成的双向链表中,即只有在删除同一个结点偶数个孩子时,才要进行级联剪枝,来维护二项树性质,奇数个时(即一个),对树影响不大,莫管它,只标记一下即可。

      为什么偶数个的时候要递归往上删除?

     二项树中在深度为i处恰有Cik个结点(I = 0, 1, 2, ……, k)。试着如果不进行级联剪枝,就可以发现,稍微删得结点超过两三个,最后的树就会不成样子,毫无章法。但是如果进行了级联剪枝,在偶数个结点时进行级联剪切时,原来是C30 = 1, C3= 3, C3= 3, C3= 1, 减少两个结点关键字后,变为:C2= 0,C21 = 2, C22 = 1;二项式是对称的,所以,偶数个结点时进行级联剪枝可以保证类似上边的正好使二项式减少一个数量级。


明天附上实现的程序


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值