克魯斯卡爾算法(Kruskal's algorithm)是兩個經典的最小生成樹算法的較爲簡單理解的一個。這裏面充分體現了貪心算法的精髓。大致的流程可以用一個圖來表示。這裏的圖的選擇借用了Wikipedia上的那個。非常清晰且直觀。
首先第一步,我們有一張圖,有若干點和邊
如下圖所示:
第一步我們要做的事情就是將所有的邊的長度排序,用排序的結果作爲我們選擇邊的依據。這裏再次體現了貪心算法的思想。資源排序,對局部最優的資源進行選擇。
排序完成後,我們率先選擇了邊AD。 這樣我們的圖就變成了
第二步,在剩下的變中尋找。我們找到了CE。這裏邊的權重也是5
依次類推我們找到了6,7,7。完成之後,圖變成了這個樣子。
下一步就是關鍵了。下面選擇那條邊呢? BC或者EF嗎?都不是,儘管現在長度爲8的邊是最小的未選擇的邊。但是現在他們已經連通了(對於BC可以通過CE,EB來連接,類似的EF可以通過EB, BA, AD, DF來接連)。所以我們不需要選擇他們。類似的BD也已經連通了(這裏的連通線用紅色表示了)。所以最後就剩下EG和FG了。當然我們選擇了EG。 最後成功的圖就是下圖:
到這裏所有的邊點都已經連通了,一個最小生成樹構建完成。
如果要簡要得描述這個算法的話就是,首先邊的權重排序。(從小到大)循環的判斷是否需要選擇這裏的邊。判斷的依據則是邊的兩個頂點是否已經連通,如果連通則繼續下一條。不連通就選擇使其連通。這個流程還是非常清晰明瞭。
但是在實現的時候,困難的地方在於如何描述2個點已然連通? 這裏用到了並查集做輔助,至於並查集可以到這裏去看看。
這裏貼出並查集的代碼和Kruscal的C++實現: