斐波那契堆

2021-06-18 21:32:27 字數 1946 閱讀 9679

斐波那契堆同二項堆一樣,也是一種可合併堆。相對於二項堆,斐波那契堆的優勢在於如果不涉及刪除元素的操作,則它的平攤執行時間為o(1)。但是由於其演算法過於複雜, 因而實際上更多的是用二項堆。

乙個斐波那契堆具有如下性質:

堆有一組有序樹組成,但是堆中的樹不一定是二項樹

斐波那契堆中的樹之間是無序的(二項堆中的樹是按照其包含的二項樹的度數排序的)

堆中每個節點的資料結構包含如下域:

指向其父節點的指標域

指向其任意乙個孩子的指標域

任意乙個節點x的所有孩子被鏈結在乙個雙向鍊錶環形鍊錶中

節點x中儲存有它的孩子的數目degree

節點x中存在乙個域mark,用於表示自從x上一次稱為另乙個節點的子女以來,它是否失掉了乙個孩子,true表示是失去了,false表示未失去

斐波那契堆中的所有樹的樹根被儲存在乙個鍊錶即根表中

對於乙個斐波那契堆,min[h]儲存了具有最小節點值的根節點

下圖即為乙個斐波那契堆的示例:

對於斐波那契堆上的各種可合併操作,關鍵思想是盡可能久地將工作推後,可以理解為斐波那契堆的操作是懶惰的。

插入新節點在斐波那契堆中非常簡單,將新的節點當做一棵新的樹的根插入到根表中即可。下圖即為乙個示例:

上圖為往斐波那契堆中新增新的節點21的情形。

合併兩個斐波那契堆的操作非常簡單,可以分為兩步:

將兩個根表通過指標合併為乙個根表(如果是c語言實現,只需要讓其中乙個根表的最後乙個節點的next指向另乙個堆的根表的頭即可)

更新min[h],這一步也很簡單,只需要比較兩個堆的min[h],取較小的即可

刪除最小節點的操作比較複雜, 推遲的工作在這裡都要被完成,其演算法思想為:

刪除最小節點,並將被刪除節點的每個孩子都看做新的堆中的一棵樹的根,將它們加入到根表中

遍歷根表,合併度數相同的樹

定義乙個輔助陣列a,a[i]=y表示樹 y 的degree值是 i,陣列的元素被初始化為null。

獲取當前根節點所在樹的degree

如果a[degree]!=null,則發現兩棵度數相同的樹,按照排序樹的要求合併它們,並更新合併後所得樹的degree(按照合併演算法,它必然是degree較大那個值加1),執行第5步

如果a[degree]!=null,則更新a[degree]為當前節點

遍歷下乙個節點

下圖即為乙個示例:

上圖即為刪除最小節點的乙個示例。

減小乙個關鍵字的字,會破壞最小堆的性質,所以要進行最小堆維護。因為斐波那契支援減小關鍵字和刪除結點操作,所以斐波那契堆的子樹就不一定是二項樹了。

減小乙個關鍵字的演算法思想如下:

減小關鍵字,如果破壞最小堆性質,則將該結點a直接從原來的樹移除直接串聯在根表中

如果節點a的父節點p沒有失去過孩子,則將父結點p的mark屬性設定成true,即標記為該節點失去過孩子,然後結束,否知執行下一步

將節點p當做被刪除節點a,將它從樹中剪掉,移到根表中

回到第2步執行

乙個示例如下圖所示:

基於較小關鍵字和刪除最小節點的操作,刪除乙個關鍵字的操作很簡單,分為如下幾步:

找到要刪除的關鍵字

將該關鍵字減小為比最小值還小的值

刪除最小關鍵字節點

斐波那契堆

以下是實現的程式 肯定可以再優化的。include include include include using namespace std class node delete m child m child null class fibonacciheap node insert int key v...

斐波那契堆

ifndef finbonacci heap h define finbonacci heap h include stdlib.h include math.h define error0 printf error at file s line d n file line 定義乙個求有符號的無窮大...

斐波那契堆

斐波那契堆的介紹 斐波那契堆是堆的一種,它和二項堆一樣,也是一種可合併堆,可用於實現合併優先佇列。而斐波那契堆比二項堆具有更好的平攤分析效能,它的合併操作的時間複雜度是o 1 與二項堆一樣,它也是由一組堆最小有序樹組成,並且是一種可合併堆。與二項堆不同的是,斐波那契堆中的樹不一定是二項樹 而且二項堆...