斐波那契堆同二項堆一樣,也是一種可合併堆。相對於二項堆,斐波那契堆的優勢在於如果不涉及刪除元素的操作,則它的平攤執行時間為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 與二項堆一樣,它也是由一組堆最小有序樹組成,並且是一種可合併堆。與二項堆不同的是,斐波那契堆中的樹不一定是二項樹 而且二項堆...