貪心演算法(Greedy Algorithm)之最小生成樹 克魯斯卡爾演算法(Kruskal's algorithm)
阿新 • • 發佈:2019-02-14
克魯斯卡爾演算法(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++實現: