【1】克魯斯卡爾算法
普里姆算法是以某頂點為起點,逐步找各頂點上最小權值的邊來構建最小生成樹。
克魯斯卡爾算法是直接以邊為目標去構建。
因為權值是在邊上,直接去找最小權值的邊來構建生成樹也是很自然的想法,只不過構建時要考慮是否會形成環路而已。
此時我們用到了圖的存儲結構中的邊集數組結構。
以下是邊集數組結構的定義代碼:
本算法所用同普里姆算法的實例,我們直接創建圖的邊集數組。
並對邊的權值從小到大排序后如下圖:
【2】克魯斯卡爾算法及詳解
克魯斯卡爾算法及其詳解:
鑒於此算法很簡單,當 i=0, i=1, i=2時執行結果可以眼觀,不再贅述。直接分析重點:
此算法的Find函數由邊數e決定,時間復雜度為O(loge),而外面有一個for循環e次。
所以克魯斯卡爾算法的時間復雜度為O(eloge)
對比兩個算法:
克魯斯卡爾算法主要針對邊展開,邊數少時效率會很高,所以對於稀疏圖有優勢
而普利姆算法對於稠密圖,即邊數非常多的情況會好些。
【3】克魯斯卡爾算法實現
實現代碼如下:

1 #include <iostream> 2 using namespace std; 3 4 #define MAXVER 9 5 #define MAXEDGE 15 6 7 typedef struct Node 8 { 9 int begin; // 起點 10 int weight; // 權值 11 int end; // 末點 12 } edgeNode; 13 14 class Graph 15 { 16 private: 17 edgeNode edge[MAXEDGE]; 18 public: 19 Graph() 20 { 21 for (int i = 0; i < MAXEDGE; ++i) 22 { 23 edge[i].begin = edge[i].weight = edge[i].end = 0; 24 } 25 } 26 ~Graph() 27 {} 28 29 public: 30 void InsertSort() 31 { 32 for (int i = 0; i < MAXEDGE- 1; ++i) 33 { 34 if (edge[i+1].weight < edge[i].weight) 35 { 36 Node temp = edge[i+1]; 37 int j = i + 1; 38 do 39 { 40 edge[j] = edge[j-1]; 41 --j; 42 } while(j >= 0 && edge[j].weight > temp.weight); 43 44 edge[j+1] = temp; 45 } 46 } 47 } 48 49 istream & operator>>(istream &in) 50 { 51 int begin, value, end; 52 cout << "請輸入15條邊的起點 終點 權值:" << endl; 53 for (int i = 0; i < MAXEDGE; ++i) 54 { 55 in >> begin >> end >> value; 56 edge[i].begin = begin; 57 edge[i].weight = value; 58 edge[i].end = end; 59 } 60 return in; 61 } 62 ostream & operator<<(ostream &out) 63 { 64 // 插入排序 65 InsertSort(); 66 out << "輸出排序邊權值后信息:" << endl; 67 for (int i = 0; i < MAXEDGE; ++i) 68 { 69 out << "edge[" << i << "] " << edge[i].begin << " " << edge[i].weight << " " << edge[i].end << endl; 70 } 71 return out; 72 } 73 // 克魯斯卡爾算法 74 void MiniSpanTree_Kruskal() 75 { 76 int i = 0, n = 0, m = 0; 77 int parent[MAXVER]; 78 for ( ; i < MAXVER; ++i) 79 parent[i] = 0; 80 for (i = 0; i < MAXEDGE; ++i) 81 { 82 n = Find(parent, edge[i].begin); 83 m = Find(parent, edge[i].end); 84 if (n != m) 85 { 86 parent[n] = m; 87 cout << " " << edge[i].begin << " " << edge[i].end << " " << edge[i].weight << endl; 88 } 89 } 90 } 91 92 int Find(int *parent, int f) 93 { 94 while (parent[f] > 0) 95 f = parent[f]; 96 return f; 97 } 98 }; 99 100 istream & operator>>(istream &in, Graph &g) 101 { 102 g >> in; 103 return in; 104 } 105 106 ostream & operator<<(ostream &out, Graph &g) 107 { 108 g << out; 109 return out; 110 } 111 112 void main() 113 { 114 Graph myg; 115 cin >> myg; 116 cout << myg; 117 myg.MiniSpanTree_Kruskal(); 118 } 119 // 備注: 120 // 最小生成樹克魯斯卡爾算法實現 121 // 整理於2013-12-04 122 // 測試需要輸入: 123 /* 124 起始 終點 權值 125 0 1 10 126 0 5 11 127 1 2 18 128 1 8 12 129 1 6 16 130 2 8 8 131 2 3 22 132 3 8 21 133 3 6 24 134 3 7 16 135 3 4 20 136 4 7 7 137 4 5 26 138 5 6 17 139 6 7 19 140 */
Good Good Study, Day Day Up.
順序 選擇 循環 總結