日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

算法导论之斐波那契堆

發布時間:2025/4/16 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 算法导论之斐波那契堆 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

斐波那契堆,和二項堆類似,也是由一組最小堆有序的樹構成。注意區別,不是二項樹,是有根而無序的樹。導論中,斐波那契堆只是具有理論上的意義,是以平攤分析為指導思想來設計的數據結構,主要是漸進時間界比二項堆有改善。斐波那契堆除去刪除元素操作外,其他操作只有O(1)的平攤運行時間,而二項堆需要O(lgn)的最壞情況運行時間。但若要斐波那契堆能轉化為實際應用,除要保證有相同平攤時間界限外,還需更簡單的數據結構。導論中提到斐波那契堆應用于最小生成樹和尋找單源最短路徑,可重點理解。

總結來說,斐波那契堆,相對二項堆來說,在多數操作上改善漸進時間,但僅適用于刪除操作動作較少的場景,且其結構復雜實用價值不大。下面看看斐波那契堆的結構及各操作的平攤分析勢能方法。

斐波那契堆的結點,包含指向父結點的指針p[x]、指向任一子女的指針child[x]、左兄弟指針left[x]、右兄弟指針right[x]、結點子女個數degree[x]、標記是否失去子女mark[x]。值得一提的是,通過左右兄弟指針,子女結點被鏈接成一個環形雙鏈表。

對給定的斐波那契堆H,通過指向包含最小關鍵字的樹根的指向min[H]來訪問,這個結點就是斐波那契堆中的最小結點。所有的樹根通過left和right指針構成一個環形雙鏈表,為堆的根表。指針min[H]指向根表中具有最小關鍵字的結點。H中所包含的結點個數為n[H]。斐波那契堆用勢能方法分析其操作的平攤性能,對給定的斐波那契堆H,t(H)表示H根表中樹的棵樹,m(H)表示H中有標記結點的個數,勢定義如下:


斐波那契堆的操作要分兩類,一類是建堆、插入結點、合并堆和抽取堆最小值;另一類是關鍵字值減少和結點刪除。

1)第一類操作斐波那契堆是一組無序的二項樹,符合二項樹的性質,性質四有所不同,描述為:無序二項樹Uk,根的度數是k,大于任何其他結點的度數;根的子女按照某種順序分別為U0,U1,…,Uk-1的根。n個結點的斐波那契堆由一組無序的二項樹構成。基本操作的平攤性能都是O(1),抽取最小值是O(lgn)。

2)第二類操作斐波那契堆是一組無序的樹,即不保持二項樹性質,操作的平攤性能是O(lgn)。

建堆、插入結點(直接作為一顆二項樹放在斐波那契堆的根表,然后將最小關鍵字指針重新調整)、尋找最小結點(第一個結點就是)、合并兩個斐波那契堆(簡單將兩個堆的根表合并即可),都是O(1)代價。重點要說明抽取最小結點的算法,和第二類中關鍵字值減小和刪除結點操作,都是O(lgn)代價。

1)抽取最小結點

抽取最小結點的處理邏輯很直接:將最小結點的子女都成為一個根,然后刪除最小結點,接著將度數相同的根鏈接起來,調整到每個度數只有一個根為止。具體算法如下:

Fun_Fib_Heap_Extract_Min(H){

??? z=min[H];

??? if z ≠ null

??????? then for each child x of z

??????????? do add x to root list of H

??????????? p[x]=null

??????? remove z from the root list of H?? //將最小結點的子女調整為根并刪除最小結點

??? if z=right[z] then min[H]=null

??? else min[H] = right[z]? //將右兄弟作為最小結點,就是堆的入口結點

???????? consolidate(H) //調整堆

??? n[H]=n[H]-1 //堆結點數減1

??? returun z

}

重點是堆調整,使根結點的度數都是唯一的,且保持無序二項樹性質。

Fun_ consolidate(H){

??? for i=0 to D(n[H]) //結點度數上界

??????? do A[i]=null

??? for each node w in the root list of H

??????? do x=w

?????????? d=degree[x]

?????????? while A[d] ≠ null

?????????????? do y=A[d]

?????????????? if key[x]<key[y] thenexchange(x,y)

?????????????? remove y form the root list of H

?????????????? make y a child of x,incrementingdegree[x]

?????????????? mark[y]=false

?????????????? A[d]=null

?????????????? d=d+1

?????????? A[d]=x //對根表中的每一個根w進行處理,使每個度數下至多只有一個根(發現有相同度數,小值作為根,大值下沉為子女),且數組A指向每一個留下的根。用A數組作為輔助數組,將根表中每個結點的度數映射過去。要對y進行標記,是勢函數計算依據。這種處理思路就使用利用結點度數0-n的最大值作為數組來存儲根表中結點的度數,是一種很有用的常量映射辦法。

??? min[H]=null

??? for i=0 to D(n[H])

??????? do if A[i] ≠ null

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

??????????????? if min[H]=null orkey[A[i]]<key[min[H]]

??????????????? ????then min[H]=A[i]

}

2)關鍵字值減小

斐波那契堆結點關鍵字值減小,主要是保持最小堆有序的性質,具體算法如下:

Fun_Fib_Heap_DecreaseKey(H,x,k){//x結點關鍵值減少為k

??? if k>key[x] then return;

??? key[x]=k

??? y=p[x]

??? if y ≠ null and key[x] <key[y]

??????? then CUT(H,x,y)

???????????? Cascading-cut(H,y)

?? If key[x] <key[min[H]] then min[H]=x

}

如果x結點減小后的關鍵值小于父結點y,則要調整堆,具體算法如下:

Fun_CUT(H,x,y){

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

??? add x to the root list of H

??? p[x] =null

??? mark[x]=false

}

將x鏈接到根表。

Fun_ Cascading-cut(H,y){

??? z=p[y]

??? if z ≠null

??????? then if mark[y]=false //失去一個子結點

??????????? then mark[y]=true

??????????? else CUT(H,y,z)

???????????????? Cascading-cut(H,z)

}

級聯處理,保持最小堆性質。刪除結點就可以通過減少結點關鍵值和抽取最小結點來完成,先把要刪除的結點關鍵值減少為負無窮大,然后抽取最小值結點來作為堆入口。


總結

以上是生活随笔為你收集整理的算法导论之斐波那契堆的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。