克魯斯卡爾(Kruskal)算法


概覽

 

相比於普里姆算法(Prim算法),克魯斯卡爾算法直接以邊為目標去構建最小生成樹。從按權值由小到大排好序的邊集合{E}中逐個尋找權值最小的邊來構建最小生成樹,只要構建時,不會形成環路即可保證當邊集合{E}中的邊都被嘗試了過后所形成的樹為最小生成樹。

 

定義

 

假設G=(V, {E})是連通網(即帶權連通圖),則令最小生成樹的初始狀態為只有N個頂點而無邊的非連通圖T=(V, {}),圖T中每個頂點自成一個連通分量。在圖G的邊集{E}中選擇權值最小的邊e,若e依附的頂點落在T中不同的連通分量上,則將e加入到T中,否則舍去e而選擇下一條權值最小的邊。以此類推,直至T中所有頂點都在同一連通分量上為止。

 

相關概念

 

連通:在無向圖G中,如果從頂點v到v’有路徑,則稱v和v’是連通的。

連通圖:如果對於圖G中任意兩個頂點vi、vj∈E,vi和vj都是連通的,則稱G是連通圖。

 

過程簡述

 

輸入:帶權連通圖(網)G的邊集E及頂點個數。(E已按權值的升序排序。)

 

初始:T=(V, {}), V是圖G的頂點集合且各頂點自成一個連通分量;表示邊的集合為空{}。

 

操作:重復以下操作,直到T中所有頂點都在同一個連通分量上。

  • 依次取E中一條邊e(邊e必為未嘗試過的邊中權值最小的邊。因為{E}已按權值升序排序)。
  • 將e的兩個頂點分別放入T的各連通分量集合V中以測試該頂點是否分別在不同連通分量中。
  • 設存在一個方法/函數Find(V, vertex),從連通分量集合V的vertex頂點開始沿該連通分量查找,返回以vertex開始的連通分量的最后一個頂點(的下標)。令n=Find(V, e.begin)和m=Find(V, e.end),若n≠m則e存在於T的不同連通分量中,故將e.end加入到以e.begin開始的連通分量中去。(注:e.begin表示e的開始頂點;e.end表示e的結束頂點;雖然無向圖的邊不存在開始頂點或結束頂點,但是作為程序表示,也得有兩個值來表示邊的兩個頂點。)(為什么n≠m則兩個頂點分別位於不同的連通分量中?若v1、v4、v6位於同一個連通分量,v3、v7位於另一個連通分量。那么怎么表示這兩個連通分量呢?可以用一個數組來表示!數組的索引本身即是頂點v的下標,而v在數組中對應的存儲單元存有構成該連通分量的下一個頂點v’。用一個數組parent表示圖T的V。那么parent[1]=4,parent[4]=6,parent[6]=0,0表示該連通圖中已無別的頂點;parent[3]=7,parent[7]=0。對於邊(1, 6)(或(6, 1)),將1帶入parent數組,最終會沿着連通圖找到n=6;將6帶入parent數組,最終會沿着連通圖找到m=6。n=m所以這兩個頂點位於相同連通圖中。而對於邊(4, 7)(或(7, 4)),將4帶入parent數組,得到n=6;將7帶入parent數組,得到m=7。n≠m所以兩個頂點位於不同連通圖中。把點v7所處的連通圖放入v1、v4、v6構成的連通圖中:parent[6]=7(parent[n]=m)反過來點v4所處的連通圖放入v3、v7構成的連通圖中,即parent[7]=6也行,只采用兩者之一即可。)
  • 直到T中所有頂點都在同一連通分量上為止。(E中的每一條邊都嘗試一遍即可。)

 

輸出:最小生成樹。

 

如何實現

 

輸入:用Edge類表示邊,其中Begin/End/Weight域分別表示邊的兩個頂點的下標及權重。Edge數組E表示邊集,N表示頂點個數。(E已按權值的升序排序。)

 

初始:用包含N個存儲單元的數組parent表示T=(V, {})的 V,即各頂點自成的連通分量。parent數組的下標i即為頂點的下標,i處存放的值parent[i]即為連通分量中下一個頂點的下標,parent[i]=0表示該連通分量已結束。將parent的各存儲單元初始化為0。

 

操作:重復以下操作,直到T中所有頂點都在同一個連通分量上。

  • 依次取E中一條邊e。
  • 將e.Begin和e.End帶入parent數組,找到連通分量中的最后一個頂點。n=Find(parent, e.Begin)和m=Find(parent, e.end),若n≠m則e存在於T的不同連通分量中,故將點e.End所處的連通圖加入到點e.Begin所處的連通圖中去,即parent[n]=m。(反過來parent[m]=n也行。)
  • 直到E中的每一條邊都嘗試一遍即可。

 

輸出:最小生成樹。

 

如上面的這個圖G=(V, {E}),其中V={v0, v1, v2, v3, v4, v5, v6, v7, v8},E= {(v4, v7, 7), (v2, v8, 8), (v0, v1, 10), (v0, v5, 11), (v1, v8, 12), (v3, v7, 16), (v1, v6, 16), (v5, v6, 17), (v1, v2, 18), (v6, v7, 19), (v3, v4, 20), (v3, v8, 21), (v2, v3, 22), (v3,v6, 24), (v4, v5, 26)}

 

用一個邊集來表示該圖G,得上圖右邊的數組。

 

① 輸入:帶權連通圖G=(V, {E})的邊集合及頂點數目,求圖G的最小生成樹。

② 初始:T={V, {}},用數組parent=int[9]來表示V,parent數組記錄的是以索引i表示的頂點開始到parent[i]表示的頂點構成的連通圖。例如:(parent數組本身就含有兩個信息:索引和索引處的值,vertex數組是不存在的,只是為了輔助理解。)

非連通圖頭頂點下標vertex:[ 0, 1, 2, 3, 4, 5, 6, 7, 8 ]

非連通圖尾頂點下標parent:[ 0, 0, 8, 0, 7, 0, 0, 0, 0 ]

parent[2]=8,parent[8]=0即頂點v2、v8構成一個連通分量。

parent[4]=7,parent[7]=0即頂點v4、v7構成一個連通分量。

③ 操作:

 

1.上圖中,邊(4, 7, 7)權值最小,取該邊為e。

 

2. 此時parent[4]=0,故n=4;parent[7]=0,故m=7;n≠m故parent[4]=7,將{v4}和{v7}這兩個連通圖合並為一個連通圖。執行后parent數組如下:

非連通圖頭頂點下標vertex:[ 0, 1, 2, 3, 4, 5, 6, 7, 8 ]

非連通圖尾頂點下標parent:[ 0, 0, 0, 0, 7, 0, 0, 0, 0 ]

 

解釋:parent[2]=0,即v2自成一個連通圖。parent[4]=7,parent[7]=0即v4所在連通圖中還有v7,v7接下來沒有別的頂點了,即v4、v7在同一個連通圖中。

3.從E中取下一條邊繼續上面1、2步驟的操作。

 

④輸出:

 

演示過程

 

(4,7) = 7

非連通圖頭頂點下標:[ 0, 1, 2, 3, 4, 5, 6, 7, 8 ]

非連通圖尾頂點下標:[ 0, 0, 0, 0, 7, 0, 0, 0, 0 ]

(2,8) = 8

非連通圖頭頂點下標:[ 0, 1, 2, 3, 4, 5, 6, 7, 8 ]

非連通圖尾頂點下標:[ 0, 0, 8, 0, 7, 0, 0, 0, 0 ]

(0,1) = 10

非連通圖頭頂點下標:[ 0, 1, 2, 3, 4, 5, 6, 7, 8 ]

非連通圖尾頂點下標:[ 1, 0, 8, 0, 7, 0, 0, 0, 0 ]

(0,5) = 11

非連通圖頭頂點下標:[ 0, 1, 2, 3, 4, 5, 6, 7, 8 ]

非連通圖尾頂點下標:[ 1, 5, 8, 0, 7, 0, 0, 0, 0 ]

(1,8) = 12

非連通圖頭頂點下標:[ 0, 1, 2, 3, 4, 5, 6, 7, 8 ]

非連通圖尾頂點下標:[ 1, 5, 8, 0, 7, 8, 0, 0, 0 ]

(3,7) = 16

非連通圖頭頂點下標:[ 0, 1, 2, 3, 4, 5, 6, 7, 8 ]

非連通圖尾頂點下標:[ 1, 5, 8, 7, 7, 8, 0, 0, 0 ]

(1,6) = 16

非連通圖頭頂點下標:[ 0, 1, 2, 3, 4, 5, 6, 7, 8 ]

非連通圖尾頂點下標:[ 1, 5, 8, 7, 7, 8, 0, 0, 6 ]

(6,7) = 19

非連通圖頭頂點下標:[ 0, 1, 2, 3, 4, 5, 6, 7, 8 ]

非連通圖尾頂點下標:[ 1, 5, 8, 7, 7, 8, 7, 0, 6 ]

 

運行結果

 

(4, 7) = 7

(2, 8) = 8

(0, 1) = 10

(0, 5) = 11

(1, 8) = 12

(3, 7) = 16

(1, 6) = 16

(6, 7) = 19

 

算法代碼

 

見鏈接:克魯斯卡爾(Kruskal)算法(代碼) - kokiafan - 博客園 (cnblogs.com)

 

復雜度

 

它的時間復雜度為O(eloge)(e為網中的邊數),所以,適合於求邊稀疏的網的最小生成樹。

 

參考資料:

《大話數據結構》 - 程傑 著 - 清華大學出版社 第252頁


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM