《算法导论3rd第十九章》斐波那契堆
前言
第六章堆排序使用了普通的二叉堆性质。其基本操作性能相当好,但union性能相当差。
对于一些图算法问题,EXTRACT-MIN 和DELETE操作次数远远小于DECREASE-KEY。因此有了斐波那契堆。
斐波那契堆结构
斐波那契堆是一系列具有最小堆序的有根树的集合。也就是说,每棵树均遵循最小堆性质:每个结点的关键字大于或等于它的父结点的关键字。
- 每个结点x包含一个指向它父结点的指针x.p和一个指向它的某一个孩子的指针x.child。x的所有孩子被链接成一个环形的双向链表,称为x的孩子链表。
- 孩子链表中的每个孩子y均有指针y.left和y.right,分别指向y的左兄弟和右兄弟。如果y是仅有的一个孩子,则y.left = y.right =y。
- 结点x的孩子链表中的孩子数目储存在x.degree。
- 布尔值属性x.mark指示结点x自从上一次成为另一个结点的孩子后,是否失去过孩子。
- 通过指针H.min来访问一个给定的斐波那契堆H,该指针指向具有最小关键字的树的根结点,我们把这个结点称为斐波那契堆的最小结点。
- 如果一个斐波那契堆H是空的,那个H.min为NIL。
- H.n表示H中当前的结点数目。
可合并堆操作
创建一个新的斐波那契堆
创建一个空的H,Make-Fib-Heap分配并返回一个Fib对象H,其中H.n = 0和H.min = NIL,H中不存在树。
插入一个结点
直接将结点插入根连表中,如果是最小点则将H.min指向它
Fib-Heap-Insert(H, x)x.degree = 0x.p = NILx.child = NILx.mark = FALSEif H.min == NILcreate a root list for H containing just xH.min = xelseinsert x into H's root listif x.key < H.min.keyH.min = xH.n = H.n + 1
寻找最小结点
最小结点可通过H.min得到。
两个斐波那契堆的合并
将H1和H2的根链表链接,然后确定新的最小结点。之后,销毁H1和H2,表示H1和H2的对象将不再使用。
Fib-Heap-Union(H1, H2)H = Make-Fib-Heap()H.min = H1.minconcatenate the root list of H2 with the root list of Hif (H1.min == NIL) or (H2.min != NIL and H2.min.key < H1.min.key)H.min = H2.minH.n = H1.n + H2.nreturn H
抽取最小结点
- 将要抽取的最小结点子树都直串在根表中
- 合并所有degree相同的树,直到没有
Fib-Heap-Extract-Min(H)z = H.minif z != NILfor each child x of zadd x to the root list of Hx.p = NILremove z from the root list of Hif z == z.rightH.min = NILelseH.min = z.rightConsolidate(H)H.n = H.n - 1return zConsolidate(H)let A[0..D(H.n)] be a new arrayfor i = 0 to D(H.n)A[i] = NILfor each node w in the root list of Hx = wd = x.degreewhile A[d] != NILy = A[d] // another node with the same degree as xif x.key > y.keyexchange x with yFib-Heap-Link(H, y, x)A[d] = NILd = d + 1A[d] = xH.min = NILfor i = 0 to D(H.n)if A[i] != NILif H.min == NILcreate a root list for H containing just A[i]H.min = A[i]elseinsert A[i] into H's root listif A[i].key < H.min.keyH.min = A[i]Fib-Heap-Link(H, y, x)remove y from the root list of Hmake y a child of x, incrementing x.degreey.mark = FALSE
练习
2-1 给出 19-4(m)中的斐波那契堆调用FIB-HEAP-EXTRACT-MIN后得到的斐波那契堆
- 7的子树到根列表中
- 合并相同degree的树
关键字减值和删除一个结点
关键字减值
- 首先,将"被减小节点"从"它所在的最小堆"剥离出来;然后将"该节点"关联到"根链表"中。 倘若被减小的节点不是单独一个节点,而是包含子树的树根。则是将以"被减小节点"为根的子树从"最小堆"中剥离出来,然后将该树关联到根链表中。
- 接着,对"被减少节点"的原父节点进行"级联剪切"。
- 最后,别忘了对根链表的最小节点进行更新。
所谓"级联剪切",就是在被减小节点破坏了最小堆性质,并被切下来之后;再从"它的父节点"进行递归级联剪切操作。
级联操作的具体动作则是:若父节点(被减小节点的父节点)的marked标记为false(默认为false),则将其设为true,然后退出。若为true,将父节点从最小堆中切下来(方式和"切被减小节点的方式"一样);然后递归对祖父节点进行"级联剪切"。
marked标记的作用就是用来标记"该节点的子节点是否有被删除过",它的作用是来实现级联剪切。而级联剪切的真正目的是为了防止"最小堆"由二叉树演化成链表。
Fib-Heap-Decrease-Key(H, x, k)if k > x.keyerror "new key is greater than current key"x.key = ky = x.pif y != NIL and x.key < y.keyCut(H, x, y)Cascading-Cut(H, y)if x.key < H.min.keyH.min = xCut(H, x, y)remove x from the child list of y, decrementing y.degreeadd x to the root list of Hx.p = NILx.mark = FALSECascading-Cut(H, y)z = y.pif z != NILif y.mark = FALSEy.makr = TRUEelseCut(H, y, z)Cascading-Cut(H, z)
删除一个结点
- 先将被删除节点的键值减少。减少后的值要比"原最小节点的值"即可。
- 取出最小节点即可。
Fib-Heap-Delete(H, x)Fib-Heap-Decrease-Key(H, x, -∞)Fib-Heap-Extract-Min(H)
增加关键字值
- 将增值节点的所有孩子放到根链表中
- 将增值节点放到根链表中,然后级联剪切
主要参考
《二项堆》
《斐波那契堆》
《斐波那契堆(一):起源》
《算法导论读书笔记(19)斐波那契堆》
《Fibonacci Heaps》
《算法导论3rd第十九章》斐波那契堆相关推荐
- 算法导论读书笔记-第十九章-斐波那契堆
算法导论第19章--斐波那契堆 可合并(最小)堆(mergeable min-heap) : 支持以下5种操作的一种数据结构, 其中每一个元素都有一个关键字: MAKE-HEAP(): 创建和返回一个 ...
- 算法导论 第20章 斐波那契堆
斐波那契堆的定义 参看19章 二项堆我们可以看到对于可合并堆操作,二项堆均有O(lgn)的时间,对于本章将要讨论的斐波那契堆也支持这些操作,而且它有着更好的渐进时间界,对于不涉及元素删除的操作,它有着 ...
- 《算法导论》第19章-斐波那契堆 引入 19.1 斐波那契堆结构
引入 1.可合并堆 可合并堆(mergeable heap)是支持以下5种操作: MAKE-HEAP():创建和返回一个新的不含任何元素的堆. INSERT(H,x):将一个已填人关键字的元素x插人堆 ...
- 《算法导论3rd第十五章》动态规划
前言 和分治法一样, 动态规划 (dynamic programming)是通过组合子问题的解而解决整个问题的.分治法是将问题划分成一些独立的子问题,递归地求解各子问题,然后合并子问题的解而得到原问题 ...
- 《算法导论3rd第二十五章》所有结点对的最短路径问题
前言 本章节,我们考虑"如何找到一个图中所有结点之间的最短路径"问题.我们通过运行|V|次上章节的单源最短路径算法解决所有结点对之间的最短路径问题,只需要每一次使用一个不同的结点作 ...
- 《算法导论3rd第十六章》贪心算法
前言 适用于最优化问题的算法往往包含一系列步骤,每个步骤都面临多种选择.使用动态规划解决最优化问题,相当于计算出每咱选择,浪费大量效率.对于"特定"下的最优化问题,可以使用更简单更 ...
- 算法导论之斐波那契堆
斐波那契堆,和二项堆类似,也是由一组最小堆有序的树构成.注意区别,不是二项树,是有根而无序的树.导论中,斐波那契堆只是具有理论上的意义,是以平摊分析为指导思想来设计的数据结构,主要是渐进时间界比二项堆 ...
- 算法导论--斐波那契堆
斐波那契堆 斐波那契堆也是数据储存结构的一种,这种数据结构之所以产生,主要有两个优点:1.对于数据合并操作具有很高的效率:2.对于其他一般数据操作平均时间复杂度较好(注意这里是平均复杂度,不是最坏情形 ...
- js算法集合(二) javascript实现斐波那契数列 (兔子数列) Javascript实现杨辉三角...
js算法集合(二) 斐波那契数列.杨辉三角 ★ 上一次我跟大家分享一下做水仙花数的算法的思路,并对其扩展到自幂数的算法,这次,我们来对斐波那契数列和杨辉三角进行研究,来加深对Javascript的理 ...
最新文章
- linux mysql odbc驱动安装_MySQL ODBC 驱动安装
- c语言 抽奖算法,腾讯2018校招笔试!抽奖算法思路c++实现!进入鹅厂真的简单!...
- Leetcode PHP题解--D7 905. Sort Array By Parity
- crontab定时任务语法及应用
- 全网首发:doubango提示text relocations错误的解决办法
- cef 加载flash 弹框_cef 3.2357之后加载flash的方法
- 我们的目标,不是没有蛀牙,是精益求精
- P1878 舞蹈课(二叉堆)
- css动感线条,使用css3制作动感导航条示例
- 涉案金额2亿多!贺金虎、刘国庆非法吸收公众存款案开庭
- 网页中那些遇到过的导航选中状态actived selected
- L3立法试水,为自动驾驶产业带来什么?
- 2020年11月总结
- 杰奇小说站PC端跳转WAP端实现方式
- JVM 优化经验总结(原文已发表在IBM开发者论坛)
- 【\u20a 错误解决】
- SQL-10-14 4-4 查询具有最高价格的机器的型号,机器包括PC、Laptop、Printer (10分)
- G003-186-04
- OpenGL入门示例8——图形平移、旋转、缩放
- 编译原理——非确定有限自动机(三)