斐波那契堆,和二项堆类似,也是由一组最小堆有序的树构成。注意区别,不是二项树,是有根而无序的树。导论中,斐波那契堆只是具有理论上的意义,是以平摊分析为指导思想来设计的数据结构,主要是渐进时间界比二项堆有改善。斐波那契堆除去删除元素操作外,其他操作只有O(1)的平摊运行时间,而二项堆需要O(lgn)的最坏情况运行时间。但若要斐波那契堆能转化为实际应用,除要保证有相同平摊时间界限外,还需更简单的数据结构。导论中提到斐波那契堆应用于最小生成树和寻找单源最短路径,可重点理解。

总结来说,斐波那契堆,相对二项堆来说,在多数操作上改善渐进时间,但仅适用于删除操作动作较少的场景,且其结构复杂实用价值不大。下面看看斐波那契堆的结构及各操作的平摊分析势能方法。

斐波那契堆的结点,包含指向父结点的指针p[x]、指向任一子女的指针child[x]、左兄弟指针left[x]、右兄弟指针right[x]、结点子女个数degree[x]、标记是否失去子女mark[x]。值得一提的是,通过左右兄弟指针,子女结点被链接成一个环形双链表。

对给定的斐波那契堆H,通过指向包含最小关键字的树根的指向min[H]来访问,这个结点就是斐波那契堆中的最小结点。所有的树根通过left和right指针构成一个环形双链表,为堆的根表。指针min[H]指向根表中具有最小关键字的结点。H中所包含的结点个数为n[H]。斐波那契堆用势能方法分析其操作的平摊性能,对给定的斐波那契堆H,t(H)表示H根表中树的棵树,m(H)表示H中有标记结点的个数,势定义如下:

斐波那契堆的操作要分两类,一类是建堆、插入结点、合并堆和抽取堆最小值;另一类是关键字值减少和结点删除。

1)第一类操作斐波那契堆是一组无序的二项树,符合二项树的性质,性质四有所不同,描述为:无序二项树Uk,根的度数是k,大于任何其他结点的度数;根的子女按照某种顺序分别为U0,U1,…,Uk-1的根。n个结点的斐波那契堆由一组无序的二项树构成。基本操作的平摊性能都是O(1),抽取最小值是O(lgn)。

2)第二类操作斐波那契堆是一组无序的树,即不保持二项树性质,操作的平摊性能是O(lgn)。

建堆、插入结点(直接作为一颗二项树放在斐波那契堆的根表,然后将最小关键字指针重新调整)、寻找最小结点(第一个结点就是)、合并两个斐波那契堆(简单将两个堆的根表合并即可),都是O(1)代价。重点要说明抽取最小结点的算法,和第二类中关键字值减小和删除结点操作,都是O(lgn)代价。

1)抽取最小结点

抽取最小结点的处理逻辑很直接:将最小结点的子女都成为一个根,然后删除最小结点,接着将度数相同的根链接起来,调整到每个度数只有一个根为止。具体算法如下:

Fun_Fib_Heap_Extract_Min(H){

z=min[H];

if z ≠ null

then for each child x of z

do add x to root list of H

p[x]=null

remove z from the root list of H   //将最小结点的子女调整为根并删除最小结点

if z=right[z] then min[H]=null

else min[H] = right[z]  //将右兄弟作为最小结点,就是堆的入口结点

consolidate(H) //调整堆

n[H]=n[H]-1 //堆结点数减1

returun z

}

重点是堆调整,使根结点的度数都是唯一的,且保持无序二项树性质。

Fun_ consolidate(H){

for i=0 to D(n[H]) //结点度数上界

do A[i]=null

for each node w in the root list of H

do x=w

d=degree[x]

while A[d] ≠ null

do y=A[d]

if key[x]<key[y] thenexchange(x,y)

remove y form the root list of H

make y a child of x,incrementingdegree[x]

mark[y]=false

A[d]=null

d=d+1

A[d]=x //对根表中的每一个根w进行处理,使每个度数下至多只有一个根(发现有相同度数,小值作为根,大值下沉为子女),且数组A指向每一个留下的根。用A数组作为辅助数组,将根表中每个结点的度数映射过去。要对y进行标记,是势函数计算依据。这种处理思路就使用利用结点度数0-n的最大值作为数组来存储根表中结点的度数,是一种很有用的常量映射办法。

min[H]=null

for i=0 to D(n[H])

do if A[i] ≠ null

then add A[i] to the root list of H

if min[H]=null orkey[A[i]]<key[min[H]]

then min[H]=A[i]

}

2)关键字值减小

斐波那契堆结点关键字值减小,主要是保持最小堆有序的性质,具体算法如下:

Fun_Fib_Heap_DecreaseKey(H,x,k){//x结点关键值减少为k

if k>key[x] then return;

key[x]=k

y=p[x]

if y ≠ null and key[x] <key[y]

then CUT(H,x,y)

Cascading-cut(H,y)

If key[x] <key[min[H]] then min[H]=x

}

如果x结点减小后的关键值小于父结点y,则要调整堆,具体算法如下:

Fun_CUT(H,x,y){

remove x from the child list ofy,decrementing degree[y]

add x to the root list of H

p[x] =null

mark[x]=false

}

将x链接到根表。

Fun_ Cascading-cut(H,y){

z=p[y]

if z ≠null

then if mark[y]=false //失去一个子结点

then mark[y]=true

else CUT(H,y,z)

Cascading-cut(H,z)

}

级联处理,保持最小堆性质。删除结点就可以通过减少结点关键值和抽取最小结点来完成,先把要删除的结点关键值减少为负无穷大,然后抽取最小值结点来作为堆入口。

算法导论之斐波那契堆相关推荐

  1. 算法导论读书笔记-第十九章-斐波那契堆

    算法导论第19章--斐波那契堆 可合并(最小)堆(mergeable min-heap) : 支持以下5种操作的一种数据结构, 其中每一个元素都有一个关键字: MAKE-HEAP(): 创建和返回一个 ...

  2. 《算法导论3rd第十九章》斐波那契堆

    前言 第六章堆排序使用了普通的二叉堆性质.其基本操作性能相当好,但union性能相当差. 对于一些图算法问题,EXTRACT-MIN 和DELETE操作次数远远小于DECREASE-KEY.因此有了斐 ...

  3. 算法导论--斐波那契堆

    斐波那契堆 斐波那契堆也是数据储存结构的一种,这种数据结构之所以产生,主要有两个优点:1.对于数据合并操作具有很高的效率:2.对于其他一般数据操作平均时间复杂度较好(注意这里是平均复杂度,不是最坏情形 ...

  4. 算法导论 第20章 斐波那契堆

    斐波那契堆的定义 参看19章 二项堆我们可以看到对于可合并堆操作,二项堆均有O(lgn)的时间,对于本章将要讨论的斐波那契堆也支持这些操作,而且它有着更好的渐进时间界,对于不涉及元素删除的操作,它有着 ...

  5. 《算法导论》第19章-斐波那契堆 引入 19.1 斐波那契堆结构

    引入 1.可合并堆 可合并堆(mergeable heap)是支持以下5种操作: MAKE-HEAP():创建和返回一个新的不含任何元素的堆. INSERT(H,x):将一个已填人关键字的元素x插人堆 ...

  6. 斐波那契堆(Fibonacci heaps)

    一:斐波那契堆 1:特性 斐波那契堆同二项堆一样,也是一种可合并堆.斐波那契堆的优势是:不涉及删除元素的操作仅需要O(1)的平摊运行时间(关于平摊分析的知识建议看<算法导论>第17章).和 ...

  7. 优先队列——斐波那契堆(without source code)

    [0]README 0.1) 本文部分内容转自 数据结构与算法分析,旨在理解 斐波那契堆 的基础知识: 0.2) 文本旨在理清 斐波那契堆的 核心idea,还没有写出源代码实现,表遗憾: 0.3)从实 ...

  8. boost::graph模块实现斐波那契堆的测试程序

    boost::graph模块实现斐波那契堆的测试程序 实现功能 C++实现代码 实现功能 boost::graph模块实现斐波那契堆的测试程序 C++实现代码 #include <boost/c ...

  9. 算法之矩阵计算斐波那契数列

    算法之矩阵计算斐波那契数列 本节内容 斐波那契介绍 普通方式求解斐波那契 矩阵概念 矩阵求幂 矩阵求解斐波那契 1.斐波那契介绍 斐波那契数列有关十分明显的特点,那是:前面相邻两项之和,构成了后一项. ...

最新文章

  1. 百度地图-解决新版百度定位失败问题
  2. cpu风扇一会转一会停_空调维修|空调开机一会就停显示e1|空调维修方法
  3. Java线程同步的一些例子
  4. 形象的解释神经网络激活函数的作用是什么
  5. WEB效能测试和负载测试部分截图
  6. hbase filter原理_HBase应用|HBase在移动广告监测产品中的应用
  7. SQL敲了mySQL变了_MySQL-Front肿么导出SQL文件
  8. 【Python爬虫】requests与urllib库的区别
  9. Atom编辑器有一个LF、CRLF的切换
  10. Qt安装Windows调试器
  11. php 压入元素,php 数组增加元素的方法 array_push 和 array_merge
  12. virtualbox vdi extend the disk usage
  13. HTTP的请求头 Last-Modified 与 If-Modified-Since 和 If-None-Match 与 ETags
  14. html远程连接mysql_mysql允许远程连接
  15. AMOS分析技术:验证性因子分析介绍;信度与效度指标详解
  16. java jre 1.8_jre1.8官方下载
  17. 轻松学会硬盘还原卡的安装和使用
  18. Java音乐播放:获取音频信息
  19. C语言编程-对数字进行分类
  20. JavaSE 知识大纲

热门文章

  1. php如何取消bak自动备份_教你如何进行异地自动备份数据库
  2. rsync常用的三种用法
  3. Nginx+Keepalived实现双机热备
  4. 在IIS上建立WAP网站的图文方法
  5. 洛谷P2312 解方程题解
  6. hibernate查询之条件查询
  7. wdcp系统升级mysql5.7.11
  8. Android 系统搜索框(有浏览记录)
  9. Excel35招必学秘技
  10. Oracle11g EM界面乱码解决方法