最小生成樹 Prim算法 Kruskal算法實現

最小生成樹定義php

最小生成樹是一副連通加權無向圖中一棵權值最小的生成樹html

在一給定的無向圖 G = (V, E) 中,(u, v) 表明鏈接頂點 u 與頂點 v 的邊(即,而 w(u, v) 表明此的權重,若存在 T 爲 E 的子集(即)且爲無循環圖,使得的 w(T) 最小,則此 T 爲 G 的最小生成樹。算法

最小生成樹實際上是最小權重生成樹的簡稱。spa

一個連通圖可能有多個生成樹。當圖中的邊具備權值時,總會有一個生成樹的邊的權值之和小於或者等於其它生成樹的邊的權值之和。廣義上而言,對於非連通無向圖來講,它的每一連通份量一樣有最小生成樹。.net

 

          ——以上內容摘自中文維基百科3d

通俗一點講就是 經過可行邊遍歷全部點,使這些邊權值相加最小(可能吧)htm

Prim算法blog

相似於dijistra算法 須要用到藍白點的思想 ……不會dijistra也不要緊 不智障就夠了排序

從單一頂點開始,普里姆算法按照如下步驟逐步擴大樹中所含頂點的數目,直到遍佈連通圖的全部頂點。ip

輸入:一個加權連通圖,其中頂點集合爲V,邊集合爲E;

初始化:Vnew = {x},其中x爲集合V中的任一節點(起始點),Enew

重複下列操做,直到Vnew = V:

{

在集合E中選取權值最小的邊(u, v),其中u爲集合Vnew中的元素,而v則是V中沒有加入Vnew的頂點(若是存在有多條知足前述條件即具備相同權值的邊,則可任意選取其中之一);

將v加入集合Vnew中,將(u, v)加入集合Enew中;

}

輸出:使用集合Vnew和Enew來描述所獲得的最小生成樹。

圖例

說明

不可選

可選

已選

 

 

此爲原始的加權連通圖。每條邊一側的數字表明其權值。

-

-

-

 

 

頂點D被任意選爲起始點。頂點A、B、E和F經過單條邊與D相連。A是距離D最近的頂點,所以將A及對應邊AD以高亮表示。

C, G

A, B, E, F

D

 

 

下一個頂點爲距離D或A最近的頂點。B距D爲9,距A爲7,E爲15,F爲6。所以,F距D或A最近,所以將頂點F與相應邊DF以高亮表示。

C, G

B, E, F

A, D

 

 

算法繼續重複上面的步驟。距離A爲7的頂點B被高亮表示。

C

B, E, G

A, D, F

 

 

在當前狀況下,能夠在C、E與G間進行選擇。C距B爲8,E距B爲7,G距F爲11。E最近,所以將頂點E與相應邊BE高亮表示。

C, E, G

A, D, F, B

 

 

這裏,可供選擇的頂點只有C和G。C距E爲5,G距E爲9,故選取C,並與邊EC一同高亮表示。

C, G

A, D, F, B, E

 

 

頂點G是惟一剩下的頂點,它距F爲11,距E爲9,E最近,故高亮表示G及相應邊EG。

G

A, D, F, B, E, C

 

 

如今,全部頂點均已被選取,圖中綠色部分即爲連通圖的最小生成樹。在此例中,最小生成樹的權值之和爲39。

A, D, F, B, E, C, G

 

Kruskal算法

基本思想:

(1)構造一個只含n個頂點,邊集爲空的子圖。若將圖中各個頂點當作一棵樹的根節點,則它是一個含有n棵樹的森林。

(2)從網的邊集 E 中選取一條權值最小的邊,若該條邊的兩個頂點分屬不一樣的樹,則將其加入子圖。也就是說,將這兩個頂點分別所在的兩棵樹合成一棵樹;反之,若該條邊的兩個頂點已落在同一棵樹上,則不可取,而應該取下一條權值最小的邊再試之

(3)依次類推,直至森林中只有一棵樹,也即子圖中含有 n-1條邊爲止。

通俗地講 就是:將圖中的全部邊都去掉,而後將邊按權值從小到大的順序添加到圖中,保證添加的過程當中不會造成環,重複上一步直到鏈接全部頂點,此時就生成了最小生成樹blahblahblah……

 

步驟:

1.新建圖G,G中擁有原圖中相同的節點,但沒有邊

2.將原圖中全部的邊按權值從小到大排序

3.從權值最小的邊開始,若是這條邊鏈接的兩個節點於圖G中不在同一個連通份量中,則添加這條邊到圖G中(並查集的思想)

4.重複3,直至圖G中全部的節點都在同一個連通份量中(即全部點都加入最小生成樹了)

 

那麼怎麼判斷兩個節點是否在一個強連通份量中呢?

 

建議先學完並查集(http://www.cnblogs.com/cyjb/p/UnionFindSets.html)

解決辦法:使用並查集,分別找出兩個頂點u, v所在樹的根節點。若根節點(祖先)相同,說明u, v在同一棵樹中(在同一個集合中),則u, v鏈接起來會造成環;若根節點不一樣,則u, v不在一棵樹中,鏈接起來不會造成環,而是將兩棵樹合併。

代碼就不貼了 

 

總結

       無疑,Kruskal算法在效率上要比Prim算法快,由於Kruskal只須要對權重邊作一次排序,而Prim算法則須要作屢次排序。儘管Prim算法每次作的算法涉及的權重邊不必定會涵蓋連通圖中的全部邊,可是隨着所使用的排序算法的效率的提升,Kruskal算法和Prim算法以前的差別將會清晰的顯性出來。

 

如有瑕疵 請諒解並糾正 感激涕零

相關文章
相關標籤/搜索