KruskalAlgorithm 克魯斯卡爾演算法

2021-10-18 19:33:51 字數 3515 閱讀 9953

克魯斯卡爾(kruskal)演算法,是用來求加權連通圖的最小生成樹的演算法。

基本思想:按照權值從小到大的順序選擇 n-1 條邊,並保證這 n-1 條邊不構成迴路

具體做法:首先構造乙個只含 n 個頂點的森林,然後依權值從小到大從連通網中選擇邊加入到森林中,並使森林中不產生迴路,直至森林變成一棵樹為止

(minimum cost spanning tree),簡稱 mst。給定乙個帶權的無向連通圖,如何選取一棵生成樹,使樹上所有邊上權的總和為最小,這叫最小生成樹

某城市新增 7 個站點(a, b, c, d, e, f, g) ,現在需要修路把 7 個站點連通

各個站點的距離用邊線表示(權) ,比如 a – b 距離 12 公里

問:如何修路保證各個站點都能連通,並且總的修建公路總里程最短?

以上圖為例,來對克魯斯卡爾進行演示(假設用陣列 r 儲存最小生成樹結果)。

邊的權值最小,因此將它加入到最小生成樹結果 r 中。

第2步:將邊加入 r 中。

上一步操作之後,邊的權值最小,因此將它加入到最小生成樹結果 r 中。

第3步:將邊加入 r 中。

上一步操作之後,邊的權值最小,因此將它加入到最小生成樹結果 r 中。

第4步:將邊加入 r 中。

上一步操作之後,邊的權值最小,但會和已有的邊構成迴路;因此,跳過邊。同理,跳過邊。將邊加入到最小生成樹結果 r 中。

第5步:將邊加入 r 中。

上一步操作之後,邊的權值最小,因此將它加入到最小生成樹結果 r 中。

第6步:將邊加入 r 中。

上一步操作之後,邊的權值最小,但會和已有的邊構成迴路;因此,跳過邊。同理,跳過邊。將邊加入到最小生成樹結果 r 中。

此時,最小生成樹構造完成!它包括的邊依次是:******。

根據前面介紹的克魯斯卡爾演算法的基本思想和做法,我們能夠了解到,克魯斯卡爾演算法重點需要解決的以下兩個問題:

問題一對圖的所有邊按照權值大小進行排序。

問題二將邊新增到最小生成樹中時,怎麼樣判斷是否形成了迴路。

問題一很好解決,採用排序演算法進行排序即可。

問題二,處理方式是:記錄頂點在"最小生成樹"中的終點,頂點的終點是"在最小生成樹中與它連通的最大頂點"。然後每次需要將一條邊新增到最小生存樹時,判斷該邊的兩個頂點的終點是否重合,重合的話則會構成迴路。

關於終點的說明:

就是將所有頂點按照從小到大的順序排列好之後;某個頂點的終點就是"與它連通的最大頂點"。

因此,接下來,雖然是權值最小的邊。但是 c 和 e 的終點都是 f,即它們的終點相同,因此,將加入最小生成樹的話,會形成迴路。這就是判斷迴路的方式。也就是說,我們加入的邊的兩個頂點不都指向同乙個終點,否則將構成迴路

public

class

kruskalalgorithm

;int

matrix =

,/*b*/

,/*c*/

,/*d*/

,/*e*/

,/*f*/

,/*g*/};

kruskalalgorithm kruskal =

newkruskalalgorithm

(vertexs, matrix)

; kruskal.

print()

; kruskal.

kruskal()

;}// 構造器

public

kruskalalgorithm

(char

vertexs,

int[

] matrix)}}

}// kruskal核心演算法

public

void

kruskal()

}// 列印"最小生成樹"

system.out.

println

("最小生成樹為");

for(

int i =

0; i < index; i++)}

// 列印鄰接矩陣

public

void

print()

}// 對邊進行排序處理

public

void

sortedges

(edata[

] edges)}}

}/**

* @param ch 表示頂點的值 'a', 'b' ...

* @return 返回頂點在頂點陣列中對應的下標,如找不到,則返回-1

*/public

intgetposition

(char ch)

}return-1

;}/** * 從鄰近矩陣中找到連通的邊

* @return 形如

*/private edata[

]getedges()

}}return edges;

}/**

* 獲取下標為 i 的頂點的終點,用於判斷兩個頂點的終點是否相同

* @param ends 用來記錄各個頂點對應的終點下標

* @param i 表示傳入頂點對應的下標

* @return 返回下標為 i 的這個頂點對應的終點下標

*/private

intgetend

(int

ends,

int i)

return i;}}

// 建立乙個類-edata,用來表示一條邊和邊上的兩個頂點

:以上大部分內容**於韓順平老師的資料結構和演算法筆記

克魯斯卡爾演算法

測試輸入包含若干測試用例。每個測試用例的第1行給出評估的道路條數 n 村莊數目m 100 隨後的 n 行對應村莊間道路的成本,每行給出一對正整數,分別是兩個村莊的編號,以及此兩村莊間道路的成本 也是正整數 為簡單起見,村莊從1到m編號。當n為0時,全部輸入結束,相應的結果不要輸出。對每個測試用例,在...

克魯斯卡爾演算法

設n v,是連通網 1 令最小生成樹的初始狀態為只有n個頂點而無邊的非連通圖t v,圖中每個頂點自成乙個連通分量 2 在e中選擇代價最小的邊,若該邊依附的頂點落在t中不同的連通分量上,則將此邊加入到t中,否則捨去此邊而選擇下一條代價最小的邊 3 反覆執行第2 步,直至t中所有頂點都在同一連通分量上為...

克魯斯卡爾演算法

via 克魯斯卡爾演算法 在連通網中求出最小生成樹 include include define maxedge 20 define maxvex 20 define infinity 65535 typedef struct mgraph typedef struct edge 對邊集陣列edge...