斐波那契堆gydF4y2Ba
一个gydF4y2Ba斐波那契堆gydF4y2Ba是具体实现的吗gydF4y2Ba堆gydF4y2Ba利用的数据结构gydF4y2Ba斐波纳契数gydF4y2Ba.使用斐波那契堆来实现gydF4y2Ba优先队列gydF4y2Ba元素gydF4y2Ba迪杰斯特拉算法gydF4y2Ba,给出了一个非常高效的运行时间。gydF4y2Ba
斐波那契堆更快gydF4y2Ba摊销gydF4y2Ba运行时间比其他堆类型长。Fibonacci堆类似于gydF4y2Ba二项堆gydF4y2Ba但斐波那契堆的结构不那么严格。二项堆立即合并堆,但斐波那契堆等待合并直到gydF4y2Ba取出最小值gydF4y2Ba
函数被调用。虽然斐波那契堆在理论上很复杂,但在实践中,其他堆类型如gydF4y2Ba配对堆gydF4y2Ba是更快。这是因为即使在最简单的实现中,Fibonacci堆每个节点都需要4个指针,而其他堆则需要2到3个。gydF4y2Ba[1]gydF4y2Ba
内容gydF4y2Ba
斐波那契堆的结构gydF4y2Ba
顾名思义,使用斐波那契堆gydF4y2Ba斐波纳契数gydF4y2Ba在它的结构。gydF4y2Ba
斐波那契数列是一系列整数的项,其中每一项是前两项的和gydF4y2Ba
最初的几个斐波那契数是gydF4y2Ba
就像gydF4y2Ba二项堆gydF4y2Ba,使用斐波那契堆gydF4y2Ba双链表gydF4y2Ba以允许gydF4y2Ba 用于诸如剪接列表的一部分、合并两个列表和查找最小(或最大值)值等操作的时间。每个节点都包含一个指向其父节点和其子节点的指针。所有子节点都链接在一个称为子节点列表的双向链表中。子列表中的每个子元素都有用于其左兄弟元素和右兄弟元素的指针。gydF4y2Ba
对于每个节点,链表还维护节点所拥有的子节点的数量、指向包含最小键的根的指针以及节点是否被标记。一个节点被标记为它失去了一个子节点,如果一个节点没有失去子节点则不被标记。见描述的gydF4y2Badecrease-keygydF4y2Ba
函数的详细信息。gydF4y2Ba
这里有一个图像显示了agydF4y2Ba单链表gydF4y2Ba和一个双链表。单链接的每个节点只有一个指针,而双链接的节点既有指向节点的指针,也有来自节点的指针。gydF4y2Ba
在斐波那契堆中,节点的度(子节点的数量)是受限制的。堆中的每个节点最多有度gydF4y2Ba
,以度为根节点的子树的大小gydF4y2Ba
至少是gydF4y2Ba
,在那里gydF4y2Ba
是第k个斐波那契数吗gydF4y2Ba[5]gydF4y2Ba.这种结构是通过一个规则来维护的,即每个非根节点最多可以剪切一个子节点。当删除第二个子节点时,节点本身需要从其父节点中删除,并成为新树的根。这意味着在操作中树木的数量减少了gydF4y2Ba取出最小值gydF4y2Ba
在那里,树木被连接在一起。gydF4y2Ba
Fibonacci堆必须满足min-heap属性(或max-heap属性,如果创建max-heap),其中每个节点的子节点的值必须小于它(父节点),因此,最小元素将始终位于树的根。gydF4y2Ba
最小功能gydF4y2Ba
下面是斐波那契堆如何实现堆的基本功能以及每个操作的时间复杂度。每个节点的子节点还使用链表进行关联。对于每个节点,链表维护节点的子节点数量以及节点是否被标记。链表还维护一个指向包含最小键的根的指针。一个节点被标记以表明它的任何子节点是否被删除。这很重要,这样堆就可以跟踪它的形状离二项堆有多远。如果斐波那契堆与二项式堆差别太大,它就会失去许多二项式性质所赋予它的有效时间操作。gydF4y2Ba
这些操作用最小Fibonacci堆来描述,但是可以很容易地将它们调整为最大Fibonacci堆操作。gydF4y2Ba
找到最小gydF4y2Ba
链表有指针,并跟踪最小节点,所以查找最小节点很简单,可以在固定的时间内完成。gydF4y2Ba
合并gydF4y2Ba
在斐波那契堆中,合并是通过简单地连接两个包含树根的列表来完成的。比较要合并的两个堆的根,其中较小的将成为新合并堆的根。另一棵树作为子树添加到这个根。这可以在固定时间内完成。gydF4y2Ba
解释为什么斐波那契堆允许常量时间合并。这意味着什么gydF4y2Ba
插入gydF4y2Ba
操作?gydF4y2Ba连接这两个列表可以在固定时间内完成。对…进行操作gydF4y2Ba链表gydF4y2Ba是常量时间,因为它只是一个更新指针的问题。比较两个堆的根也是常数时间。gydF4y2Ba自gydF4y2Ba
插入gydF4y2Ba
只是取要插入的节点并把它当作堆来处理要与我们插入节点的堆合并,我们调用gydF4y2Ba合并gydF4y2Ba
在两个。这意味着gydF4y2Ba插入gydF4y2Ba
也是常数时间。gydF4y2Ba
提取最小gydF4y2Ba
取出最小值gydF4y2Ba
是关于斐波那契堆的最重要的操作之一。斐波那契堆的速度优势很大程度上来自于它将操作后的堆合并延迟到gydF4y2Ba取出最小值gydF4y2Ba
被称为。另一方面,二项堆会立即合并。当违反堆属性时就会发生合并,例如,如果两个堆具有相同的顺序,则必须调整堆以防止这种情况发生。gydF4y2Ba
删除最小元素分为三个步骤。节点从根列表中删除,节点的子节点被添加到根列表中。接下来,如果需要,将更新最小元素。最后,巩固树木,这样就不会有重复的次序。如果发生了任何合并,请确保在需要时更新最小元素。延迟合并可以节省时间。gydF4y2Ba
下面的两张图片显示了gydF4y2Ba取出最小值gydF4y2Ba
函数在介绍中所示的斐波那契堆。gydF4y2Ba
插入gydF4y2Ba
插入到斐波那契堆类似于gydF4y2Ba插入gydF4y2Ba
二项堆的运算。方法创建一个元素的堆,并将两个堆合并gydF4y2Ba合并gydF4y2Ba
函数。如果有必要,将更新最小元素指针。树中的节点总数增加1。gydF4y2Ba
删除gydF4y2Ba
若要删除元素,请减小使用键值gydF4y2Ba降低关键gydF4y2Ba
到负无穷,然后调用gydF4y2Ba取出最小值gydF4y2Ba
.当节点的值为负无穷时,因为堆是最小堆,所以它将成为树的根。gydF4y2Ba取出最小值gydF4y2Ba
将删除顶部元素,因此这样做将删除相关节点。gydF4y2Ba
降低关键gydF4y2Ba
减小键值时可能会出现两种情况:更改会导致堆冲突,或者不会。gydF4y2Ba
如果堆属性没有被破坏,只需减少gydF4y2Ba .gydF4y2Ba
如果确实发生了冲突,则将节点的父节点删除。如果父节点不是根节点,则标记它。如果它已经被标记,那么它也将被删除,并标记它的父节点,以此类推。继续这个过程,直到到达根节点或未标记的节点。接下来,如果最小值是新的最小值,则将最小指针设置为减小的值。gydF4y2Ba[5]gydF4y2Ba
当删除节点的子节点时,reduce键函数将标记该节点。这允许它跟踪关于每个节点的一些历史。本质上,标记跟踪gydF4y2Ba[9]gydF4y2Ba:gydF4y2Ba
- 节点没有删除子节点(未标记)gydF4y2Ba
- 该节点删除了一个子节点(标记)gydF4y2Ba
- 该节点即将删除第二个子节点(删除已标记节点的子节点)gydF4y2Ba
实现gydF4y2Ba
下面是斐波那契堆的伪代码实现gydF4y2Ba[10]gydF4y2Ba[11]gydF4y2Ba.gydF4y2Ba
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17日18 19 20 21日22日23日24日25日26日27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100gydF4y2Ba |
|
Python实现的斐波那契堆可能很长,但是gydF4y2Ba在这里gydF4y2Ba是一个示例Python实现。gydF4y2Ba
斐波那契堆的运行时间总结gydF4y2Ba
操作gydF4y2Ba | 平摊运行时间gydF4y2Ba |
插入gydF4y2Ba | |
删除gydF4y2Ba | |
找到最小值gydF4y2Ba | |
取出最小值gydF4y2Ba | |
降低关键gydF4y2Ba | |
合并gydF4y2Ba |
根据一篇论文gydF4y2Ba[12]gydF4y2Ba由Michael Fredman (Fibonacci堆的发明者之一)所写,Fibonacci堆有几个缺点:许多计算机科学家声称,它们很难编程,而且它们理论上优秀的运行时间在实践中并不总是比理论上较差的堆类型更好。gydF4y2Ba
另请参阅gydF4y2Ba
参考文献gydF4y2Ba
- , .gydF4y2BaFibonacci_HeapgydF4y2Ba.2016年6月25日,从gydF4y2Bahttps://en.wikipedia.org/wiki/Fibonacci_heapgydF4y2Ba
- B。gydF4y2BaFibonacci_HeapgydF4y2Ba.2016年6月7日,从gydF4y2Bahttps://en.wikipedia.org/wiki/File:Fibonacci_heap.pnggydF4y2Ba
- ,L。gydF4y2BaDoubly-linked-list.svggydF4y2Ba.2016年6月25日,从gydF4y2Bahttps://en.wikipedia.org/wiki/File:Doubly-linked-list.svggydF4y2Ba
- ,L。gydF4y2BaSingly-linked-list.svggydF4y2Ba.2016年6月25日,从gydF4y2Bahttps://en.wikipedia.org/wiki/File:Singly-linked-list.svggydF4y2Ba
- , .gydF4y2Ba斐波那契堆gydF4y2Ba.2016年6月7日,从gydF4y2Bahttps://en.wikipedia.org/wiki/Fibonacci_heapgydF4y2Ba
- ,M。gydF4y2Ba斐波那契堆extractmin1.pnggydF4y2Ba.2016年6月7日,从gydF4y2Bahttps://en.wikipedia.org/wiki/File:Fibonacci_heap_extractmin1.pnggydF4y2Ba
- B。gydF4y2Ba斐波那契堆extractmin2.pnggydF4y2Ba.2016年6月7日,从gydF4y2Bahttps://en.wikipedia.org/wiki/File:Fibonacci_heap_extractmin2.pnggydF4y2Ba
- B。gydF4y2Ba斐波那契heap-decreasekey.pnggydF4y2Ba.2016年6月7日,从gydF4y2Bahttps://en.wikipedia.org/wiki/File:Fibonacci_heap-decreasekey.pnggydF4y2Ba
- imm, D。gydF4y2Ba斐波那契堆gydF4y2Ba.2016年6月7日,从gydF4y2Bahttp://www.growingwiththeweb.com/2014/06/fibonacci-heap.htmlgydF4y2Ba
- Stergiopoulos, S。gydF4y2Ba斐波那契堆操作的算法gydF4y2Ba.2016年6月7日,从gydF4y2Bahttp://www.cse.yorku.ca/~aaw/Sotirios/BinomialHeapAlgorithm.htmlgydF4y2Ba
- Cormen, T., Leiserson, C., Rivest, R., & Stein, C.(2001)。gydF4y2Ba算法导论(第二版)gydF4y2Ba(pp. 20章)。麻省理工学院出版社。gydF4y2Ba
- Fredman, M., Sedgewick, R., Sleator, D., and Tarjan, R.gydF4y2Ba配对堆:一种新的自调整堆形式gydF4y2Ba.2016年6月7日,从gydF4y2Bahttps://www.cs.cmu.edu/~sleator/papers/pairing-heaps.pdfgydF4y2Ba