克魯斯卡爾算法(Kruskal's algorithm)是兩個經典的最小生成樹算法的較為簡單理解的一個。這里面充分體現了貪心算法的精髓。算法如下:
假設T中的邊和頂點均塗成紅色,其余邊為白色。開始時G中的邊均為白色。
1)將所有頂點塗成紅色;
2)在白色邊中,挑選一條權最小的邊,使其與紅色邊不形成圈,將該白色邊塗紅;
3)重復2)直到有n-1條紅色邊,這n-1條紅色邊便構成最小生成樹T的邊集合。
注意到在算法執行過程中,紅色頂點和紅色邊會形成一個或多個連通分支,它們都是G的子樹。一條邊與紅色邊形成圈當且僅當這條邊的兩個端點屬於同一個子樹。因此判定一條邊是否與紅色邊形成圈,只需判斷這條邊的兩端點是否屬於同一個子樹。
上述判斷可以如此實現:給每個子樹一個不同的編號,對每一個頂點引入一個標記t,表示這個頂點所在的子樹編號。當加入一條紅色邊,就會使該邊兩端點所在的兩個子樹連接起來,成為一個子樹,從而兩個子樹中的頂點標記要改變成一樣。綜上,可將Kruskal算法細化使其更容易計算機實現。
我的實現結果如下:(200個節點)

java部分代碼如下:
public static void kruskal(Graph g) { // 每個頂點加編號 int[] parent = new int[g.MAX_VERTEX ]; for (int i = 0; i < g.MAX_VERTEX; i++) { parent[i] = i; } // 找到n-1條邊,既滿足條件 while (result.size() < (g.MAX_VERTEX-1) ) { // 取最小邊 double min = MOUSTMAX; int jtemp=0; int i = 0; for(int k=0;k<g.MAX_VERTEX;k++){ for (int j = 0; j < g.MAX_VERTEX; j++) { // System.out.println("-------------"+k+"--"+j + "parent[" + k + "]--"+parent[k]+"parent[" + j+"]" +parent[j] + "--"+g.L1_Matrix[k][j] + "min" + min); if ((parent[k] != parent[j] ) && g.L1_Matrix[k][j] < min) { min = g.L1_Matrix[k][j]; jtemp = j; i=k; } } } int jj = parent[i]; int kk = parent[jtemp]; proc.add("------選中結點 "+i+" 與結點 "+jtemp + " ,路徑長度:" + g.L1_Matrix[i][jtemp]); //判斷該邊的兩個端點是否在同一個子樹中: // 不在:將該邊加入結果集 // 在:繼續循環 if (kk != jj) { int tempi = parent[i]; //將新找到的邊的頂點與以前的頂點標志值設為一樣,注意要把以前的頂點相連的頂點都要同步改變值 for(int j = 0; j<parent.length;j++){ if(parent[j] == tempi ) parent[j] = parent[jtemp]; } //取出已經加入的邊 boolean temp = true; for(Vertex[] v:result){ if(v[0] == g.vertexList[i] && v[1] ==g.vertexList[jtemp]){ temp = false; } if(v[1] == g.vertexList[i] && v[0] ==g.vertexList[jtemp]){ temp = false; } } if(temp){ result.add(new Vertex[] { g.vertexList[i],g.vertexList[jtemp] } ); } //將已找到的邊,權值設為最大 g.L1_Matrix[i][jtemp] = MOUSTMAX; } } }
---------------------------------------------------------
參見:http://home.ustc.edu.cn/~chh1990/win/
-------------------------------------------------------------------
