总结:这一章讲了斐波那契堆,它是一种比二项堆更松散的堆,它由一组无序的二项树组成,对不涉及删除元素的操作,它仅需O(1)的平摊运行时间。本章介绍斐波那契堆的插入、合并、删除等操作。

1.    斐波那契堆的结构

每个结点x的域:

1)  父节点p[x]

2)  指向任一子女的指针child[x]

3)  左兄弟left[x]

4)  右兄弟right[x]

5)  子女的个数degree[x]

6)  布尔值域mark[x]

在斐波那契堆中,结点x的子女被链接成一个环形双链表,称为x的子女表。当left[x]=right[x]=x时,说明x是独子。

mark域记录了每个结点的一小段历史:

1)  在某个时刻,x是个根

2)  然后,x被链接到另一个结点上(CONSOLIDATE (FIB-HEAP-LINK) )

3)  再通过切断来去除x的两个子女(CUT, CASCADING-CUT)

一旦第二个孩子失掉了,x与其父节点之间的联系就被切断了,x成为一个新根。如果发生了第1步和第2步,且x的一个孩子被切割掉了,则mark[x]为TRUE。

在一个斐波那契堆中,所有树的根都通过用其left和right指针链接成一个环形的双链表,称为该堆的根表。min[H]指向根表中具有最小关键字的结点。n[H]代表H中目前包含的结点个数。

势函数:Φ(H) = t(H) + 2m(H),其中t(H)为根表中树的棵树,m(H)为H中有标记的结点的个数。

最大度数:结点最大度数的上界D(n)=O(lgn)

2.    可合并堆的操作

1)创建

MAKE-FIB-HEAP,分配并返回一个斐波那契堆对象H,且n[H]=0, min[H]=NIL。

实际代价:O(1)

势:Φ(H)=0

平摊代价:O(1)

2)插入

插入操作直接将结点插入根表中。

实际代价:O(1)

势的增加:(t(H)+1+2m(H))-(t(H)+2m(H))=1

平摊代价:O(1)+1=O(1)

伪代码

FIB-HEAP-INSERT(H,x)

degree[x] <- 0

p[x] <- NIL

child[x] <- NIL

left[x] <- x

right[x] <- x

mark[x] <- FALSE

concatenate the root list containing x with root list H

if min[H]=NIL or key[min[H]] > key[x]

then min[H] <- x

n[H] <- n[H]+1

3)寻找最小结点

min[H]指向最小结点

实际代价:O(1)

势的增加:0

平摊代价:O(1)

4)合并

直接将两个堆的根表并置,并确定新的min[H]

实际代价:O(1)

势的增加:0

平摊代价:O(1)

伪代码

FIB-HEAP-UNION(H1,H2)

H <- MAKE-FIB-HEAP()

min[H] <- min[H1]

concatenate the root list of H2 with the root list of H

if(min[H]=NIL or key[min[H1]]>key[min[H2]])

then min[H] <- min[H2]

n[H] <- n[H1]+n[H2]

free the objects H1 and H2

return H

5)抽取最小结点

先将最小结点的每个子女都成为一个根,然后将度数相同的根链接起来。注意,直到这里,才真正完成了根表中的树的合并。

实际代价:O(D(n)+t(H))

势的增加:至多(D(n)+1+2m(H))-(t(H)+2m(H))=D(n)-t(H)+1

平摊代价:O(D(n))=O(lgn)

伪代码

FIB-HEAP-EXTRACT-MIN(H)

z <- min[H]

if z!=NIL

then for each child x of z

do add x to the root list of H

p[x] <- NIL

remove z from the root list of H

if z=right[z]

then min[H] <- NIL

else min[H] <- right[z]

CONSOLIDATE(H)

n[H] <- n[H]-1

return z

CONSOLIDATE(H)将H根表中的度数相同的结点链接起来,直到根表中每个度数至多只有一个根。用到辅助数组A[0…D(n[H])],A[i]=y代表degree[y]=i

伪代码

CONSOLIDATE(H)

for i <- 0 to D(n[H])

do A[i] <- NIL

for each node w in the root list of H

do x <- w

d <- degree[x]

while A[d]!=NIL

do y <- A[d]

if key[y]<key[x]

then exchange y <-> x

FIB-HEAP-LINK(H,y,x)

A[d] <- NIL

d <- d+1

A[d] <- x

min[H] <- NIL

for i <- 0 to D(n[H])

do if A[i]!=NIL

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

if min[H]=NIL or key[A[i]]<key[min[H]]

then min[H] <- A[i]

伪代码

FIB-HEAP-LINK(H,y,x)

remove y from the root list of H

make y a child of x, incrementing degree[x]

mark[y] <- FALSE

6)减小一个关键字

若结点的关键字减小后,关键字小于其父节点的关键字,则将此结点移出,置入根表中,另外,还需执行级联切断操作。

伪代码

FIB-HEAP-DECREASE-KEY(H,x,k)

if k > key[x]

then error “error”

key[x] <- k

y <- p[x]

if y!=NIL and key[x]<key[y]

then CUT(H,x,y)

CASCADING-CUT(H,y)

if key[x]<key[min[H]]

then min[H] <- x

伪代码

CUT(H,x,y)

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

add x to the root list of H

p[x] <- NIL

mark[x] <- FALSE

由于CUT使切断的结点的父节点y又失去了一个孩子,因此CASCADING-CUT判断父节点的MARK,若为FALSE,则由于y失去了一个孩子,设mark[y]为TRUE,若mark[y]已经为TRUE了,那么y已经失去了两个孩子了,那么继续切断y与p[y],再接着判断p[y]的MARK,一直沿树递归上去,直到找到一个根节点或未加标记的结点。

伪代码

CASCADING(H,y)

z <- p[y]

if z!=NIL

then if mark[y]=FALSE

then mark[y]=TRUE

else CUT(H,y,z)

CASCADING-CUT(H,z)

复杂度分析:

设递归调用了c次CASCADING()

实际代价:O(c)

势的变化:至多(t(H)+c+2(m(H)-c+2))-(t(H)+2m(H))=4-c (c-1个结点被级联切断消除标记,最后一次CASCADING-CUT可能给某个结点加上标记)

平摊代价:O(c)+4-c=O(1)

7)删除

平摊代价:O(lgn)

伪代码

FIB-HEAP-DELETE(H,x)

FIB-HEAP-DECREASE-KEY(H,x,-INF)

FIB-HEAP-EXTRACT-MIN(H)

斐波那契堆(不太详尽)相关推荐

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

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

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

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

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

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

  4. 算法导论之斐波那契堆

    斐波那契堆,和二项堆类似,也是由一组最小堆有序的树构成.注意区别,不是二项树,是有根而无序的树.导论中,斐波那契堆只是具有理论上的意义,是以平摊分析为指导思想来设计的数据结构,主要是渐进时间界比二项堆 ...

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

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

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

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

  7. 二项堆与斐波那契堆各个操作时间复杂度

    过程 二项堆 斐波那契堆 MAKE_HEAP Θ(1) Θ(1) INSERT Ω(lgn) Θ(1) MINIMUM Ω(lgn) Θ(1) EXTRACT-MIN Θ(lgn) O(lgn) UN ...

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

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

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

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

最新文章

  1. 学习笔记Spark(九)—— Spark MLlib应用(1)—— 机器学习简介、Spark MLlib简介
  2. python celery多worker、多队列、定时任务
  3. 自编码器深度分析+定制特征描述子构建初探
  4. linux内核配置与编译
  5. Flutter入门:application、module、package、plugin
  6. Git之添加公钥之后git clone ****提示sign_and_send_pubkey: signing failed: agent refused operation
  7. figma下载_如何在Figma中创建逼真的3D对象
  8. 急救WINDOWS内存错误
  9. 力扣 ---- java
  10. 如何实现一个文件系统
  11. 十分钟搞清字符集和字符编码
  12. 路由器和交换机哪个更好?路由器交换机怎么连接?
  13. Linux Capability探索实验
  14. Linux的文件夹是中文怎么用cd进入目录
  15. 一只兔子帮你理解 kNN
  16. Axue8.0基础使用篇
  17. php中文数组按拼音排序问题
  18. 编程培训怎么样 哪家编程培训机构靠谱
  19. SylixOS更新记录
  20. 同轴电缆技术参数(一)

热门文章

  1. hbase集群 数据写入_一种构建HBase集群全文索引方法,数据读取方法以及数据写入方法与流程...
  2. Lightgbm如何处理类别特征?
  3. OData的初步认识
  4. Struts1.x系列教程(1):用MyEclipse开发第一个Struts程序
  5. python -- 计算 平方,乘方,平方根
  6. 数据赋能 兴业惠民 | 山东省第三届数据应用创新创业大赛潍坊分赛场火热报名中
  7. 哔哩哔哩漫画-下载地址分析
  8. 【离散数学】集合与关系
  9. 每一个JAVA程序员都应该怀揣一个架构师的梦,这样你的职业发展前景一片大好...
  10. 项目感受|总结|献给怀揣着梦想来到兄弟连学习的兄弟姐妹们