本博客的代碼的思想和圖片參考:好大學慕課浙江大學陳越老師、何欽銘老師的《數據結構》node
最小生成樹的概念:是由圖生成而來的git
是一棵樹算法
1.無迴路數據結構
2.若是有V個定點就有V-1條邊less
是生成樹ide
1.包含圖中全部的節點V測試
2.V-1條邊都在圖裏面ui
3.邊的權重和最小。this
4.向生成樹中添加任意一條邊都構成迴路。spa
「貪」:每一步都要最好的。
「好」:權重最小的邊
約束條件:
1.只能使用圖裏面的邊
2.只能正好使用V-1條邊
3.不能有迴路
1.先選擇一個頂點做爲樹的根節點,把這個根節點當成一棵樹
2.選擇圖中距離這棵樹最近可是沒有被樹收錄的一個頂點,把他收錄在樹中,而且保證不構成迴路
3.按照這樣的方法,把全部的圖的頂點一一收錄進樹中。
4.若是沒有頂點能夠收錄
a.若是圖中的頂點數量等於樹的頂點數量-->最小生成樹構造完成
b. 若是圖中的頂點數量不等於樹的頂點數量-->此圖不連通
下面使用圖片來具體描述此算法的算法思想:
經過咱們對算法的描述,咱們發現Prim算法和Dijkstra算法很相似
void Prim()
{
MST = {s};
while (1) {
V = 未收錄頂點中dist最小者;
if ( 這樣的V不存在 )
break;
將V收錄進MST: dist[V] = 0;
for ( V 的每一個鄰接點 W )
if ( dist[W]!=W未被收錄 0 )
if ( E (V,W) < dist[W] ){
dist[W] = E (V,W) ;
parent[W] = V;
}
}
if ( MST中收的頂點不到|V|個 )
Error ( 「生成樹不存在」 );
}
對於Prim算法
1.dist表明的是什麼,應該如何被初始化
dist表明距離當前生成樹的最小距離。和根節點直接相鄰的初始化爲權重,其餘的初始化爲正無窮。等每插入一個樹節點,對dist進行更新。對於已經收錄的節點,更新其dist=0
2.該算法的時間複雜度是多少
該算法時間複雜度在於如何去 」未收錄頂點中dist最小者」若是是使用暴力搜索的方法,那麼時間複雜的爲T=O(n^2).此種算法對於稠密圖比較適用。
使用貪心算法,每次獲取權重最小的邊,可是不能讓生成樹構成迴路。直到去到V-1條邊爲止。
下面仍是使用一個圖來講明次算法
僞代碼描述
void Kruskal ( Graph G )
{
MST = { } ;
while ( MST 中不到 |V| 1 條邊 && E 中還有邊 ) {
從 E 中取一條權重最小的邊 E (v,w) ; /* 最小堆 */
將 E (v,w) 從 E 中刪除;
if ( E (V,W) 不在 MST 中構成迴路) /* 並查集 */
將 E (V,W) 加入 MST;
else
完全無視 E (V,W) ;
}
}
if ( MST 中不到 |V| 1 條邊 )
Error ( 「生成樹不存在」 );
}
如何實現「從 E 中取一條權重最小的邊 E (v,w) 」---->最小堆
如何判斷是否產生迴路------>」 並查集」
此算法的時間複雜的爲T=O(ELogE),次算法對稀疏圖比較友好. 若是改圖是稠密圖,那麼E=v^2
時間複雜度和Prim算法差很少
下面經過一道練習題來比較Prim算法和Kruskal算法的優劣
題目的PTA連接
https://pta.patest.cn/pta/test/3512/exam/4/question/85491
題目內容:
現有村落間道路的統計數據表中,列出了有可能建設成標準公路的若干條道路的成本,求使每一個村落都有公路連通所須要的最低成本。
輸入數據包括城鎮數目正整數N(≤1000)和候選道路數目M(≤3N);隨後的M行對應M條道路,每行給出3個正整數,分別是該條道路直接連通的兩個城鎮的編號以及該道路改建的預算成本。爲簡單起見,城鎮從1到N編號。
輸出村村通須要的最低成本。若是輸入數據不足以保證暢通,則輸出−1,表示須要建設更多公路。
6 151 2 51 3 31 4 71 5 41 6 22 3 42 4 62 5 22 6 63 4 63 5 13 6 14 5 104 6 85 6 3
12
代碼能夠在最後的連接裏面
上面的習題其實很簡單,就是Prim算法和Kruskal算法的應用。很簡單,只須要改一下輸出便可。
Prim算法在PTA的運行結果:
Kruskal算法在PTA的運行結果:
從內存的使用狀況來看,Prim算法使用的鄰接矩陣來存儲圖,Kruskal算法使用鄰接表來存儲圖,從圖中能夠看出,鄰接矩陣在最N時內存由1M增加到8M,而鄰接表的內存始終是在1M。因而可知在同等的數據量的狀況下,鄰接表比鄰接矩陣更加節省內存空間。
就本題的測試結果來看,Kruskal算法的時間複雜度是優於Prim算法的。本題的N最大爲1000
M(edge)最大爲3N,遠遠比不上稠密圖M=N^2,只能算是稀疏圖。因此在稀疏圖的狀況下,Kruskal算法時間複雜的度較好。和理論的證實一致。
Prim算法求最小生成樹的權重和打印路徑代碼:
1 /* 2 * prim.c 3 * 4 * Created on: 2017年5月15日 5 * Author: ygh 6 */ 7 #include <stdio.h> 8 #include <stdlib.h> 9 10 #define MAX_VERTEX_NUM 100 /*define the max number of the vertex*/ 11 #define INFINITY 65535 /*define double byte no negitive integer max number is 65535*/ 12 #define ERROR -1 13 14 typedef int vertex; /*define the data type of the vertex*/ 15 typedef int weightType; /*define the data type of the weight*/ 16 typedef char dataType; /*define the data type of the vertex value*/ 17 18 /*define the data structure of the Edge*/ 19 typedef struct eNode *ptrToENode; 20 typedef struct eNode { 21 vertex v1, v2; /*two vertex between the edge <v1,v2>*/ 22 weightType weight; /*the value of the edge's weight */ 23 }; 24 typedef ptrToENode edge; 25 26 /*==================A adjacent matrix to describe a graph=========================================*/ 27 28 /*define the data structure of the graph*/ 29 typedef struct gMNode *ptrTogMNode; 30 typedef struct gMNode { 31 int vertex_number; /*the number of the vertex*/ 32 int edge_nunber; /*the number of the edge*/ 33 weightType g[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; /*define the adjacent matrix weight of graph*/ 34 dataType data[MAX_VERTEX_NUM]; /*define the dataType array to store the value of vertex*/ 35 }; 36 typedef ptrTogMNode adjacentMatrixGraph; /*a graph show by adjacent matrix*/ 37 38 /* 39 create a graph given the vertex number. 40 @param vertexNum The verter number of the graph 41 @return a graph with vertex but no any egdgs 42 */ 43 adjacentMatrixGraph createMGraph(int vertexNum) { 44 vertex v, w; 45 adjacentMatrixGraph graph; 46 graph = (adjacentMatrixGraph) malloc(sizeof(struct gMNode)); 47 graph->vertex_number = vertexNum; 48 graph->edge_nunber = 0; 49 /*initialize the adjacent matrix*/ 50 for (v = 0; v < graph->vertex_number; v++) { 51 for (w = 0; w < graph->vertex_number; w++) { 52 graph->g[v][w] = INFINITY; 53 } 54 } 55 56 return graph; 57 } 58 59 /* 60 insert a edge to graph.We will distinct oriented graph and undirected graph 61 @param graph The graph you want to insert edge 62 @param e The edge you want to insert the graph 63 @param isOriented Whether the graph is oriented graph.If the graph is oriented 64 we will set adjacent matrix [n][m]=[m][n]=edge's weight,else we only set 65 the adjacent matrix [n][m]=edge's weight 66 */ 67 void inserEdgeToMatrix(adjacentMatrixGraph graph, edge e, int isOriented) { 68 graph->g[e->v1][e->v2] = e->weight; 69 if (!isOriented) { 70 graph->g[e->v2][e->v1] = e->weight; 71 } 72 } 73 74 /* 75 construct a graph according user's input 76 77 @return a graph has been filled good 78 */ 79 adjacentMatrixGraph buildMGraph(int isOrdered) { 80 adjacentMatrixGraph graph; 81 edge e; 82 vertex i; 83 int vertex_num; 84 scanf("%d", &vertex_num); 85 graph = createMGraph(vertex_num); 86 scanf("%d", &(graph->edge_nunber)); 87 if (graph->edge_nunber) { 88 e = (edge) malloc(sizeof(struct eNode)); 89 for (i = 0; i < graph->edge_nunber; i++) { 90 scanf("%d %d %d", &e->v1, &e->v2, &e->weight); 91 e->v1--; 92 e->v2--; 93 inserEdgeToMatrix(graph, e, isOrdered); 94 } 95 } 96 return graph; 97 98 } 99 100 /*==================A adjacent link to describe a graph=========================================*/ 101 /*define the data structure adjacent table node*/ 102 typedef struct adjNode *ptrToAdjNode; 103 typedef struct adjNode { 104 vertex adjVerx; /*the index of the vertex*/ 105 weightType weight; /*the value of the weight*/ 106 ptrToAdjNode next; /*the point to point the next node*/ 107 }; 108 109 /*define the data structure of the adjacent head*/ 110 typedef struct vNode *ptrToVNode; 111 typedef struct vNode { 112 ptrToAdjNode head; /*the point to point the adjacent table node*/ 113 dataType data; /*the space to store the name of the vertex,but some time the vertex has no names*/ 114 } adjList[MAX_VERTEX_NUM]; 115 116 /*define the data structure of graph*/ 117 typedef struct gLNode *ptrTogLNode; 118 typedef struct gLNode { 119 int vertex_number; /*the number of the vertex*/ 120 int edge_nunber; /*the number of the edge*/ 121 adjList g; /*adjacent table*/ 122 }; 123 typedef ptrTogLNode adjacentTableGraph; /*a graph show by adjacent table*/ 124 125 /* 126 create a graph given the vertex number. 127 @param vertexNum The verter number of the graph 128 @return a graph with vertex but no any egdgs 129 */ 130 adjacentTableGraph createLGraph(int vertexNum) { 131 adjacentTableGraph graph; 132 133 vertex v; 134 graph = (adjacentTableGraph) malloc(sizeof(struct gLNode)); 135 graph->vertex_number = vertexNum; 136 graph->edge_nunber = 0; 137 /*initialize the adjacent table*/ 138 for (v = 0; v < graph->vertex_number; v++) { 139 graph->g[v].head = NULL; 140 } 141 return graph; 142 } 143 144 /* 145 insert a edge to graph.We will distinct oriented graph and undirected graph 146 The e->v1 and e->v2 are the vertexs' indexs in the adjacent table 147 @param graph The graph you want to insert edge 148 @param e The edge you want to insert the graph 149 @param isOriented Whether the graph is oriented graph.If the graph is oriented 150 we will set adjacent table graph[v1]->head=v2 and set graph[v1].head=v2 151 otherwise we only set graph[v1].head=v2 152 */ 153 void insertEdgeToLink(adjacentTableGraph graph, edge e, int isOriented) { 154 /*build node<v1,v2>*/ 155 ptrToAdjNode newNode; 156 newNode = (ptrToAdjNode) malloc(sizeof(struct adjNode)); 157 newNode->adjVerx = e->v2; 158 newNode->weight = e->weight; 159 newNode->next = graph->g[e->v1].head; 160 graph->g[e->v1].head = newNode; 161 /*if the graph is directed graph*/ 162 if (!isOriented) { 163 newNode = (ptrToAdjNode) malloc(sizeof(struct adjNode)); 164 newNode->adjVerx = e->v1; 165 newNode->weight = e->weight; 166 newNode->next = graph->g[e->v2].head; 167 graph->g[e->v2].head = newNode; 168 } 169 } 170 171 /* 172 build a graph stored by adjacent table 173 */ 174 adjacentTableGraph buildLGraph() { 175 adjacentTableGraph graph; 176 edge e; 177 vertex i; 178 int vertex_num; 179 180 scanf("%d", &vertex_num); 181 graph = createLGraph(vertex_num); 182 scanf("%d", &(graph->edge_nunber)); 183 if (graph->edge_nunber) { 184 e = (edge) malloc(sizeof(struct eNode)); 185 for (i = 0; i < graph->edge_nunber; i++) { 186 scanf("%d %d %d", &e->v1, &e->v2, &e->weight); 187 insertEdgeToLink(graph, e, 0); 188 } 189 } 190 191 return graph; 192 } 193 194 /* 195 * Find the minimal node closest to created tree 196 */ 197 vertex findMinDist(adjacentMatrixGraph graph, weightType dist[]) { 198 vertex minV, v; 199 weightType minDist = INFINITY; 200 for (v = 0; v < graph->vertex_number; v++) { 201 if (dist[v] != 0 && dist[v] < minDist) { 202 minDist = dist[v]; 203 minV = v; 204 } 205 } 206 if (minDist < INFINITY) { 207 return minV; 208 } else { 209 return ERROR; 210 } 211 } 212 213 /* 214 * Prim algorithms,we will store the minimal created tree with a adjacent 215 * list table and return the minimal weight 216 * @param mGraph The graph showed by adjacent matrix is to store graph 217 * @param lGraph The graph showed by adjacent list is to store the minimal created tree 218 * @return The weight of the minimal created tree if the graph is connected, otherwise return 219 * <code>ERROR</code> 220 */ 221 int prim(adjacentMatrixGraph mGraph, adjacentTableGraph lGraph) { 222 223 weightType dist[mGraph->vertex_number], totalWeight; 224 vertex parent[mGraph->vertex_number], v, w; 225 int vCounter; 226 edge e; 227 228 /* 229 * Initialize dist and parent,default the start point is 0 index 230 */ 231 for (v = 0; v < mGraph->vertex_number; v++) { 232 dist[v] = mGraph->g[0][v]; 233 parent[v] = 0; 234 } 235 236 /* 237 * Initialize weight and vertex counter 238 */ 239 totalWeight = 0; 240 vCounter = 0; 241 /* 242 * Initialize a edge 243 */ 244 e = (edge) malloc(sizeof(struct eNode)); 245 246 /* 247 * Initialize dist[0] as the root of tree and set parent[0] to -1 248 */ 249 dist[0] = 0; 250 vCounter++; 251 parent[0] = -1; 252 /* 253 * Execute Prim algorithms 254 */ 255 while (1) { 256 v = findMinDist(mGraph, dist); 257 if (v == ERROR) { 258 break; 259 } 260 261 /* 262 * Put <v,parent[v]> to tree 263 */ 264 e->v1 = parent[v]; 265 e->v2 = v; 266 e->weight = dist[v]; 267 insertEdgeToLink(lGraph, e, 1); 268 totalWeight += dist[v]; 269 vCounter++; 270 dist[v] = 0; 271 272 /* 273 * Update the v adjacent vertex distance with minimal tree 274 */ 275 for (w = 0; w < mGraph->vertex_number; w++) { 276 /* 277 * If w is v adjacent vetex and not be added to minimal tree 278 */ 279 if (dist[w] != 0 && mGraph->g[v][w] < INFINITY) { 280 /* 281 * Update the distance to minimal created tree 282 */ 283 if (mGraph->g[v][w] < dist[w]) { 284 dist[w] = mGraph->g[v][w]; 285 parent[w] = v; 286 } 287 } 288 } 289 } 290 if (vCounter < mGraph->vertex_number) { 291 return ERROR; 292 } else { 293 return totalWeight; 294 } 295 } 296 297 /*========Use DFS to print the result of the minimal created tree==========*/ 298 /* 299 * A method to access graph 300 */ 301 void visit(adjacentTableGraph graph, vertex v) { 302 printf("%d ", v); 303 } 304 305 /* 306 Depth first search a graph 307 @param graph The graph need to search 308 @param startPoint The fisrt point we start search the graph 309 @paran int *visited The array we use to tag the vertex we has accessed. 310 */ 311 void DFS(adjacentTableGraph graph, vertex startPoint, int *visited) { 312 ptrToAdjNode p; 313 visit(graph, startPoint); 314 p = graph->g[3].head; 315 visited[startPoint] = 1; 316 for (p = graph->g[startPoint].head; p; p = p->next) { 317 if (visited[p->adjVerx] == 0) { 318 DFS(graph, p->adjVerx, visited); 319 } 320 } 321 } 322 323 /* 324 * Initialize a visited array that make them all to zero 325 */ 326 void initVisited(int length, int *visited) { 327 int i; 328 for (i = 0; i < length; i++) { 329 visited[i] = 0; 330 } 331 } 332 333 int main() { 334 adjacentTableGraph lGraph; 335 adjacentMatrixGraph mGraph = buildMGraph(0); 336 vertex visited[mGraph->vertex_number]; 337 lGraph = createLGraph(mGraph->vertex_number); 338 weightType totalWeigt = prim(mGraph, lGraph); 339 printf("totalWeigh:%d\n", totalWeigt); 340 initVisited(mGraph->vertex_number, visited); 341 DFS(lGraph, 0, visited); 342 return 0; 343 }
測試數據和運行結果:
1 7 12 2 1 2 2 3 1 4 1 4 2 5 10 5 2 4 3 6 3 1 4 7 3 6 5 8 4 3 2 9 4 6 8 10 4 7 4 11 4 5 7 12 5 7 6 13 7 6 1 14 15 Test result: 16 totalWeigh:16 17 0 1 3 6 4 5 2
Kruskal算法求最小生成樹的權重和打印路徑代碼:
1 /* 2 * kruskal.c 3 * 4 * Created on: 2017年5月15日 5 * Author: ygh 6 */ 7 8 #include <stdio.h> 9 #include <stdlib.h> 10 11 #define MAX_VERTEX_NUM 10001 /*define the max number of the vertex*/ 12 #define INFINITY 65535 /*define double byte no negitive integer max number is 65535*/ 13 #define ERROR -1 14 15 typedef int vertex; /*define the data type of the vertex*/ 16 typedef int weightType; /*define the data type of the weight*/ 17 typedef char dataType; /*define the data type of the vertex value*/ 18 19 /*define the data structure of the Edge*/ 20 typedef struct eNode *ptrToENode; 21 typedef struct eNode { 22 vertex v1, v2; /*two vertex between the edge <v1,v2>*/ 23 weightType weight; /*the value of the edge's weight */ 24 }; 25 typedef ptrToENode edge; 26 27 /*==================A adjacent link to describe a graph=========================================*/ 28 /*define the data structure adjacent table node*/ 29 typedef struct adjNode *ptrToAdjNode; 30 typedef struct adjNode { 31 vertex adjVerx; /*the index of the vertex*/ 32 weightType weight; /*the value of the weight*/ 33 ptrToAdjNode next; /*the point to point the next node*/ 34 }; 35 36 /*define the data structure of the adjacent head*/ 37 typedef struct vNode *ptrToVNode; 38 typedef struct vNode { 39 ptrToAdjNode head; /*the point to point the adjacent table node*/ 40 dataType data; /*the space to store the name of the vertex,but some time the vertex has no names*/ 41 } adjList[MAX_VERTEX_NUM]; 42 43 /*define the data structure of graph*/ 44 typedef struct gLNode *ptrTogLNode; 45 typedef struct gLNode { 46 int vertex_number; /*the number of the vertex*/ 47 int edge_nunber; /*the number of the edge*/ 48 adjList g; /*adjacent table*/ 49 }; 50 typedef ptrTogLNode adjacentTableGraph; /*a graph show by adjacent table*/ 51 52 /* 53 create a graph given the vertex number. 54 @param vertexNum The verter number of the graph 55 @return a graph with vertex but no any egdgs 56 */ 57 adjacentTableGraph createLGraph(int vertexNum) { 58 adjacentTableGraph graph; 59 60 vertex v; 61 graph = (adjacentTableGraph) malloc(sizeof(struct gLNode)); 62 graph->vertex_number = vertexNum; 63 graph->edge_nunber = 0; 64 /*initialize the adjacent table*/ 65 for (v = 0; v < graph->vertex_number; v++) { 66 graph->g[v].head = NULL; 67 } 68 return graph; 69 } 70 71 /* 72 insert a edge to graph.We will distinct oriented graph and undirected graph 73 The e->v1 and e->v2 are the vertexs' indexs in the adjacent table 74 @param graph The graph you want to insert edge 75 @param e The edge you want to insert the graph 76 @param isOriented Whether the graph is oriented graph.If the graph is oriented 77 we will set adjacent table graph[v1]->head=v2 and set graph[v1].head=v2 78 otherwise we only set graph[v1].head=v2 79 */ 80 void insertEdgeToLink(adjacentTableGraph graph, edge e, int isOriented) { 81 /*build node<v1,v2>*/ 82 ptrToAdjNode newNode; 83 newNode = (ptrToAdjNode) malloc(sizeof(struct adjNode)); 84 newNode->adjVerx = e->v2; 85 newNode->weight = e->weight; 86 newNode->next = graph->g[e->v1].head; 87 graph->g[e->v1].head = newNode; 88 /*if the graph is directed graph*/ 89 if (!isOriented) { 90 newNode = (ptrToAdjNode) malloc(sizeof(struct adjNode)); 91 newNode->adjVerx = e->v1; 92 newNode->weight = e->weight; 93 newNode->next = graph->g[e->v2].head; 94 graph->g[e->v2].head = newNode; 95 } 96 } 97 98 /* 99 build a graph stored by adjacent table 100 */ 101 adjacentTableGraph buildLGraph(int isOrdered) { 102 adjacentTableGraph graph; 103 edge e; 104 vertex i; 105 int vertex_num; 106 107 scanf("%d", &vertex_num); 108 graph = createLGraph(vertex_num); 109 scanf("%d", &(graph->edge_nunber)); 110 if (graph->edge_nunber) { 111 e = (edge) malloc(sizeof(struct eNode)); 112 for (i = 0; i < graph->edge_nunber; i++) { 113 scanf("%d %d %d", &e->v1, &e->v2, &e->weight); 114 e->v1--; 115 e->v2--; 116 insertEdgeToLink(graph, e, isOrdered); 117 } 118 } 119 120 return graph; 121 } 122 123 /*----------------------define collection and some operator of graph's nodes-----------------------------*/ 124 125 /* 126 * The element of collection 127 */ 128 typedef vertex elementType; 129 130 /* 131 * The index of root element,we use it as the collection name 132 */ 133 typedef vertex setName; 134 135 /* 136 * A array to store the collection,we set the 137 * first index is 0 138 */ 139 typedef elementType setType[MAX_VERTEX_NUM]; 140 141 /* 142 * Initialize collection 143 * @param A <code>elementType</code> array to store the collections,maybe 144 * many collection will be stored in this array 145 * @param n The length of the collection 146 */ 147 void initializeVSet(setType s, int n) { 148 elementType x; 149 for (x = 0; x < n; x++) { 150 s[x] = -1; 151 } 152 } 153 154 /* 155 * Union two collections which is showed by root element.We will union smaller collection 156 * to greater collection and we will update the quantity for greater collection 157 * @param s A <code>elementType</code> array to store the collections,maybe 158 * many collection will be stored in this array 159 * @param root1 The root element of the first collection 160 * @param root2 The root element of the second collection 161 */ 162 void unionCollection(setType s, setName root1, setName root2) { 163 /* 164 * If root2's quantity greater than root1 165 */ 166 if (s[root2] < s[root1]) { 167 s[root2] += s[root1]; 168 s[root1] = root2; 169 } else { 170 s[root1] += s[root2]; 171 s[root2] = root1; 172 } 173 } 174 175 /* 176 * Find the element in which collection and use the root element 177 * to represent this collection and return it.In this method,we will compress path 178 * @param s A <code>elementType</code> array to store the collections,maybe 179 * many collection will be stored in this array 180 * @param x The element we find which collection it in. 181 */ 182 setName find(setType s, elementType x) { 183 if (s[x] < 0) { 184 return x; 185 } else { 186 /* 187 *compress path 188 */ 189 return s[x] = find(s, s[x]); 190 } 191 } 192 193 /* 194 * Check v1 and v1 whether is belong to a same collection. If not union these 195 * two collection,otherwise do nothing. 196 * @param vSet A <code>elementType</code> array to store the collections,maybe 197 * many collection will be stored in this array 198 * @param v1 The index of node in the graph,also the element is the collection. 199 * @param v2 The index of node in the graph,also the element is the collection. 200 * @return If the two element is belong same collection,union them and return 1 201 * else do nothing and return 0; 202 */ 203 int checkCircle(setType vSet, vertex v1, vertex v2) { 204 setName root1 = find(vSet, v1); 205 setName root2 = find(vSet, v2); 206 if (root1 == root2) { 207 return 0; 208 } else { 209 unionCollection(vSet, root1, root2); 210 return 1; 211 } 212 } 213 214 /*-------------define the minimal heap of edge-------------------*/ 215 216 /* 217 * Update the tree whose root element index is p into minimal heap,we use the edgs's 218 * weight as the to construct the minimal heap. 219 * 220 * @param eset A array of edge to store the heap,because the edge is point variable 221 * So the eSet is a edge type array,you can compare it with <code>int* arr</code> 222 * @param The index of the root element. 223 * @param n The length of the heap,the max index is n-1 in this case. And 224 * this heap index is start from zero. 225 */ 226 void percDowm(edge eSet, int p, int n) { 227 int parent, child; 228 struct eNode x; 229 230 x = eSet[p]; 231 for (parent = p; (parent * 2 + 1) < n; parent = child) { 232 /* 233 * Because the first index if from zero,so the left child 234 * is parent*2+1 235 */ 236 child = parent * 2 + 1; 237 /* 238 * Find smaller weigh between the left child and right child 239 */ 240 if ((child != n - 1) && eSet[child].weight > eSet[child + 1].weight) { 241 child++; 242 } 243 if (x.weight <= eSet[child].weight) { 244 break; 245 } else { 246 eSet[parent] = eSet[child]; 247 } 248 } 249 eSet[parent] = x; 250 } 251 252 /* 253 * Initialize eSet heap and update it to be the minimal heap 254 * @param graph A graph which is stored by adjacent list 255 * @param eSet A array of the edge as the minimal heap 256 */ 257 void initializeESet(adjacentTableGraph graph, edge eSet) { 258 vertex v; 259 ptrToAdjNode w; 260 int counter = 0; 261 for (v = 0; v < graph->vertex_number; v++) { 262 for (w = graph->g[v].head; w; w = w->next) { 263 /* 264 * expect for put same edge to it,we only 265 * put <v1,v2> to it. 266 */ 267 if (v < w->adjVerx) { 268 eSet[counter].v1 = v; 269 eSet[counter].v2 = w->adjVerx; 270 eSet[counter].weight = w->weight; 271 counter++; 272 } 273 274 } 275 } 276 /* 277 * Initialize the minimal heap 278 */ 279 for (counter = graph->edge_nunber / 2; counter >= 0; counter--) { 280 percDowm(eSet, counter, graph->edge_nunber); 281 } 282 } 283 284 /* 285 * Get minimal edge from the minimal weight heap 286 * @param eset A array of edge to store the heap,because the edge is point variable 287 * So the eSet is a edge type array,you can compare it with <code>int* arr</code> 288 * @param The current size of the minimal heap 289 * @return The index of the minimal edge in this heap(array) 290 */ 291 int getEdge(edge eSet, int currentSize) { 292 if (currentSize == 0) { 293 return currentSize - 1; 294 } 295 struct eNode temp = eSet[currentSize - 1]; 296 eSet[currentSize - 1] = eSet[0]; 297 eSet[0] = temp; 298 percDowm(eSet, 0, currentSize - 1); 299 return currentSize - 1; 300 } 301 302 /* 303 * Implement the kruskal algorithms to find the minimal created tree 304 * Algorithms thought:we choose the minimal edge from graph but don't 305 * construct a circle each time. Until we choose the V-1 edges. The V 306 * is equal with the quantity of the graph's vertex 307 * In this program,we will use a counter to record the quantity of edges 308 * At last of this method,if we check the quantity of the edge is less than 309 * V-1, it indicates the graph is not collected,so -1 will be return,otherwise we will return 310 * the minimal created tree total weight. 311 * @param graph A graph which is stored by adjacent list 312 * @param mst A A graph which is stored by adjacent list to store the minimal created tree 313 * @return If the graph is collected,the weight of the minimal created tree 314 * will be return, otherwise return -1 315 */ 316 int kruskal(adjacentTableGraph graph, adjacentTableGraph mst) { 317 /* 318 * totalWeight is to record the total weight 319 * of the minimal created tree 320 */ 321 weightType totalWeight; 322 /* 323 * eCounter is to record the quantity of edges which has been 324 * insert the <code>mst<code> 325 * 326 * nextEdge is to record the next minimal edge in the minimal heap 327 */ 328 int eCounter, nextEdge; 329 330 /* 331 *A set of the vertex to store the vertex and implement 332 *some operation such as union find and so on 333 */ 334 setType vSet; 335 336 /* 337 * A array of edge to as the minimal heap to store the egdes 338 */ 339 edge eSet; 340 341 /* 342 * Initialize some variables 343 */ 344 initializeVSet(vSet, graph->vertex_number); 345 eSet = (edge) malloc((sizeof(struct eNode)) * (graph->edge_nunber)); 346 initializeESet(graph, eSet); 347 // mst = createLGraph(graph->vertex_number); 348 totalWeight = 0; 349 eCounter = 0; 350 nextEdge = graph->edge_nunber; 351 while (eCounter < graph->vertex_number - 1) { 352 nextEdge = getEdge(eSet, nextEdge); 353 if (nextEdge < 0) { 354 break; 355 } 356 /* 357 * Check whether a circle between two vertex 358 */ 359 if (checkCircle(vSet, eSet[nextEdge].v1, eSet[nextEdge].v2)) { 360 insertEdgeToLink(mst, eSet + nextEdge, 0); 361 totalWeight += eSet[nextEdge].weight; 362 eCounter++; 363 } 364 } 365 if (eCounter < graph->vertex_number - 1) { 366 totalWeight = -1; 367 } 368 return totalWeight; 369 } 370 371 /*========Use DFS to print the result of the minimal created tree==========*/ 372 /* 373 * A method to access graph 374 */ 375 void visit(adjacentTableGraph graph, vertex v) { 376 printf("%d ", v); 377 } 378 379 /* 380 Depth first search a graph 381 @param graph The graph need to search 382 @param startPoint The fisrt point we start search the graph 383 @paran int *visited The array we use to tag the vertex we has accessed. 384 */ 385 void DFS(adjacentTableGraph graph, vertex startPoint, int *visited) { 386 ptrToAdjNode p; 387 visit(graph, startPoint); 388 p = graph->g[3].head; 389 visited[startPoint] = 1; 390 for (p = graph->g[startPoint].head; p; p = p->next) { 391 if (visited[p->adjVerx] == 0) { 392 DFS(graph, p->adjVerx, visited); 393 } 394 } 395 } 396 397 /* 398 * Initialize a visited array that make them all to zero 399 */ 400 void initVisited(int length, int *visited) { 401 int i; 402 for (i = 0; i < length; i++) { 403 visited[i] = 0; 404 } 405 } 406 407 int main() { 408 adjacentTableGraph graph = buildLGraph(0); 409 adjacentTableGraph mst = createLGraph(graph->vertex_number); 410 vertex visited[graph->vertex_number]; 411 weightType totalWeight = kruskal(graph, mst); 412 printf("totalWeight:%d\n", totalWeight); 413 initVisited(graph->vertex_number, visited); 414 DFS(mst, 0, visited); 415 return 0; 416 }
測試數據和運行結果
1 7 12 2 1 2 2 3 1 4 1 4 2 5 10 5 2 4 3 6 3 1 4 7 3 6 5 8 4 3 2 9 4 6 8 10 4 7 4 11 4 5 7 12 5 7 6 13 7 6 1 14 15 Test result: 16 totalWeigh:16 17 0 1 3 6 4 5 2
上面村村通習題的Prim代碼
1 /* 2 * path.c 3 * 4 * Created on: 2017年5月15日 5 * Author: ygh 6 */ 7 #include <stdio.h> 8 #include <stdlib.h> 9 10 #define MAX_VERTEX_NUM 10001 /*define the max number of the vertex*/ 11 #define INFINITY 65535 /*define double byte no negitive integer max number is 65535*/ 12 #define ERROR -1 13 14 typedef int vertex; /*define the data type of the vertex*/ 15 typedef int weightType; /*define the data type of the weight*/ 16 typedef char dataType; /*define the data type of the vertex value*/ 17 18 /*define the data structure of the Edge*/ 19 typedef struct eNode *ptrToENode; 20 typedef struct eNode { 21 vertex v1, v2; /*two vertex between the edge <v1,v2>*/ 22 weightType weight; /*the value of the edge's weight */ 23 }; 24 typedef ptrToENode edge; 25 26 /*==================A adjacent matrix to describe a graph=========================================*/ 27 28 /*define the data structure of the graph*/ 29 typedef struct gMNode *ptrTogMNode; 30 typedef struct gMNode { 31 int vertex_number; /*the number of the vertex*/ 32 int edge_nunber; /*the number of the edge*/ 33 weightType g[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; /*define the adjacent matrix weight of graph*/ 34 dataType data[MAX_VERTEX_NUM]; /*define the dataType array to store the value of vertex*/ 35 }; 36 typedef ptrTogMNode adjacentMatrixGraph; /*a graph show by adjacent matrix*/ 37 38 /* 39 create a graph given the vertex number. 40 @param vertexNum The verter number of the graph 41 @return a graph with vertex but no any egdgs 42 */ 43 adjacentMatrixGraph createMGraph(int vertexNum) { 44 vertex v, w; 45 adjacentMatrixGraph graph; 46 graph = (adjacentMatrixGraph) malloc(sizeof(struct gMNode)); 47 graph->vertex_number = vertexNum; 48 graph->edge_nunber = 0; 49 /*initialize the adjacent matrix*/ 50 for (v = 0; v < graph->vertex_number; v++) { 51 for (w = 0; w < graph->vertex_number; w++) { 52 graph->g[v][w] = INFINITY; 53 } 54 } 55 56 return graph; 57 } 58 59 /* 60 insert a edge to graph.We will distinct oriented graph and undirected graph 61 @param graph The graph you want to insert edge 62 @param e The edge you want to insert the graph 63 @param isOriented Whether the graph is oriented graph.If the graph is oriented 64 we will set adjacent matrix [n][m]=[m][n]=edge's weight,else we only set 65 the adjacent matrix [n][m]=edge's weight 66 */ 67 void inserEdgeToMatrix(adjacentMatrixGraph graph, edge e, int isOriented) { 68 graph->g[e->v1][e->v2] = e->weight; 69 if (!isOriented) { 70 graph->g[e->v2][e->v1] = e->weight; 71 } 72 } 73 74 /* 75 construct a graph according user's input 76 77 @return a graph has been filled good 78 */ 79 adjacentMatrixGraph buildMGraph(int isOrdered) { 80 adjacentMatrixGraph graph; 81 edge e; 82 vertex i; 83 int vertex_num; 84 scanf("%d", &vertex_num); 85 graph = createMGraph(vertex_num); 86 scanf("%d", &(graph->edge_nunber)); 87 if (graph->edge_nunber) { 88 e = (edge) malloc(sizeof(struct eNode)); 89 for (i = 0; i < graph->edge_nunber; i++) { 90 scanf("%d %d %d", &e->v1, &e->v2, &e->weight); 91 e->v1--; 92 e->v2--; 93 inserEdgeToMatrix(graph, e, isOrdered); 94 } 95 } 96 return graph; 97 98 } 99 100 /*==================A adjacent link to describe a graph=========================================*/ 101 /*define the data structure adjacent table node*/ 102 typedef struct adjNode *ptrToAdjNode; 103 typedef struct adjNode { 104 vertex adjVerx; /*the index of the vertex*/ 105 weightType weight; /*the value of the weight*/ 106 ptrToAdjNode next; /*the point to point the next node*/ 107 }; 108 109 /*define the data structure of the adjacent head*/ 110 typedef struct vNode *ptrToVNode; 111 typedef struct vNode { 112 ptrToAdjNode head; /*the point to point the adjacent table node*/ 113 dataType data; /*the space to store the name of the vertex,but some time the vertex has no names*/ 114 } adjList[MAX_VERTEX_NUM]; 115 116 /*define the data structure of graph*/ 117 typedef struct gLNode *ptrTogLNode; 118 typedef struct gLNode { 119 int vertex_number; /*the number of the vertex*/ 120 int edge_nunber; /*the number of the edge*/ 121 adjList g; /*adjacent table*/ 122 }; 123 typedef ptrTogLNode adjacentTableGraph; /*a graph show by adjacent table*/ 124 125 /* 126 create a graph given the vertex number. 127 @param vertexNum The verter number of the graph 128 @return a graph with vertex but no any egdgs 129 */ 130 adjacentTableGraph createLGraph(int vertexNum) { 131 adjacentTableGraph graph; 132 133 vertex v; 134 graph = (adjacentTableGraph) malloc(sizeof(struct gLNode)); 135 graph->vertex_number = vertexNum; 136 graph->edge_nunber = 0; 137 /*initialize the adjacent table*/ 138 for (v = 0; v < graph->vertex_number; v++) { 139 graph->g[v].head = NULL; 140 } 141 return graph; 142 } 143 144 /* 145 insert a edge to graph.We will distinct oriented graph and undirected graph 146 The e->v1 and e->v2 are the vertexs' indexs in the adjacent table 147 @param graph The graph you want to insert edge 148 @param e The edge you want to insert the graph 149 @param isOriented Whether the graph is oriented graph.If the graph is oriented 150 we will set adjacent table graph[v1]->head=v2 and set graph[v1].head=v2 151 otherwise we only set graph[v1].head=v2 152 */ 153 void insertEdgeToLink(adjacentTableGraph graph, edge e, int isOriented) { 154 /*build node<v1,v2>*/ 155 ptrToAdjNode newNode; 156 newNode = (ptrToAdjNode) malloc(sizeof(struct adjNode)); 157 newNode->adjVerx = e->v2; 158 newNode->weight = e->weight; 159 newNode->next = graph->g[e->v1].head; 160 graph->g[e->v1].head = newNode; 161 /*if the graph is directed graph*/ 162 if (!isOriented) { 163 newNode = (ptrToAdjNode) malloc(sizeof(struct adjNode)); 164 newNode->adjVerx = e->v1; 165 newNode->weight = e->weight; 166 newNode->next = graph->g[e->v2].head; 167 graph->g[e->v2].head = newNode; 168 } 169 } 170 171 /* 172 build a graph stored by adjacent table 173 */ 174 adjacentTableGraph buildLGraph() { 175 adjacentTableGraph graph; 176 edge e; 177 vertex i; 178 int vertex_num; 179 180 scanf("%d", &vertex_num); 181 graph = createLGraph(vertex_num); 182 scanf("%d", &(graph->edge_nunber)); 183 if (graph->edge_nunber) { 184 e = (edge) malloc(sizeof(struct eNode)); 185 for (i = 0; i < graph->edge_nunber; i++) { 186 scanf("%d %d %d", &e->v1, &e->v2, &e->weight); 187 insertEdgeToLink(graph, e, 0); 188 } 189 } 190 191 return graph; 192 } 193 194 /* 195 * Find the minimal node closest to created tree 196 */ 197 vertex findMinDist(adjacentMatrixGraph graph, weightType dist[]) { 198 vertex minV, v; 199 weightType minDist = INFINITY; 200 for (v = 0; v < graph->vertex_number; v++) { 201 if (dist[v] != 0 && dist[v] < minDist) { 202 minDist = dist[v]; 203 minV = v; 204 } 205 } 206 if (minDist < INFINITY) { 207 return minV; 208 } else { 209 return ERROR; 210 } 211 } 212 213 /* 214 * Prim algorithms,we will store the minimal created tree with a adjacnet 215 * list table and return the minimal weight 216 * @param mGraph The graph showed by adjacent matrix is to store graph 217 * @param lGraph The graph showed by adjacent list is to store the minimal created tree 218 * @return The weight of the minimal created tree if the graph is connected, otherwise return 219 * <code>ERROR</code> 220 */ 221 int prim(adjacentMatrixGraph mGraph, adjacentTableGraph lGraph) { 222 223 weightType dist[mGraph->vertex_number], totalWeight; 224 vertex parent[mGraph->vertex_number], v, w; 225 int vCounter; 226 edge e; 227 228 /* 229 * Initialize dist and parent,default the start point is 0 index 230 */ 231 for (v = 0; v < mGraph->vertex_number; v++) { 232 dist[v] = mGraph->g[0][v]; 233 parent[v] = 0; 234 } 235 236 /* 237 * Initialize weight and vertex counter 238 */ 239 totalWeight = 0; 240 vCounter = 0; 241 /* 242 * Initialize a edge 243 */ 244 e = (edge) malloc(sizeof(struct eNode)); 245 246 /* 247 * Initialize dist[0] as the root of tree and set parent[0] to -1 248 */ 249 dist[0] = 0; 250 vCounter++; 251 parent[0] = -1; 252 /* 253 * Execute Prim algorithms 254 */ 255 while (1) { 256 v = findMinDist(mGraph, dist); 257 if (v == ERROR) { 258 break; 259 } 260 261 /* 262 * Put <v,parent[v]> to tree 263 */ 264 e->v1 = parent[v]; 265 e->v2 = v; 266 e->weight = dist[v]; 267 insertEdgeToLink(lGraph, e, 1); 268 totalWeight += dist[v]; 269 vCounter++; 270 dist[v] = 0; 271 272 /* 273 * Update the v adjacent vertex distance with minimal tree 274 */ 275 for (w = 0; w < mGraph->vertex_number; w++) { 276 /* 277 * If w is v adjacent vetex and not be added to minimal tree 278 */ 279 if (dist[w] != 0 && mGraph->g[v][w] < INFINITY) { 280 /* 281 * Update the distance to minimal created tree 282 */ 283 if (mGraph->g[v][w] < dist[w]) { 284 dist[w] = mGraph->g[v][w]; 285 parent[w] = v; 286 } 287 } 288 } 289 } 290 if (vCounter < mGraph->vertex_number) { 291 return ERROR; 292 } else { 293 return totalWeight; 294 } 295 } 296 297 /*========Use DFS to print the result of the minimal created tree==========*/ 298 /* 299 * A method to access graph 300 */ 301 void visit(adjacentTableGraph graph, vertex v) { 302 printf("%d ", v); 303 } 304 305 /* 306 Depth first search a graph 307 @param graph The graph need to search 308 @param startPoint The fisrt point we start search the graph 309 @paran int *visited The array we use to tag the vertex we has accessed. 310 */ 311 void DFS(adjacentTableGraph graph, vertex startPoint, int *visited) { 312 ptrToAdjNode p; 313 visit(graph, startPoint); 314 p = graph->g[3].head; 315 visited[startPoint] = 1; 316 for (p = graph->g[startPoint].head; p; p = p->next) { 317 if (visited[p->adjVerx] == 0) { 318 DFS(graph, p->adjVerx, visited); 319 } 320 } 321 } 322 323 /* 324 * Initialize a visited array that make them all to zero 325 */ 326 void initVisited(int length, int *visited) { 327 int i; 328 for (i = 0; i < length; i++) { 329 visited[i] = 0; 330 } 331 } 332 333 int main() { 334 adjacentTableGraph lGraph; 335 adjacentMatrixGraph mGraph = buildMGraph(0); 336 vertex visited[mGraph->vertex_number]; 337 lGraph = createLGraph(mGraph->vertex_number); 338 weightType totalWeigt = prim(mGraph, lGraph); 339 printf("%d\n", totalWeigt); 340 return 0; 341 }
上面村村通習題的Kruskal代碼
1 /* 2 * kruskal.c 3 * 4 * Created on: 2017年5月15日 5 * Author: ygh 6 */ 7 8 #include <stdio.h> 9 #include <stdlib.h> 10 11 #define MAX_VERTEX_NUM 10001 /*define the max number of the vertex*/ 12 #define INFINITY 65535 /*define double byte no negitive integer max number is 65535*/ 13 #define ERROR -1 14 15 typedef int vertex; /*define the data type of the vertex*/ 16 typedef int weightType; /*define the data type of the weight*/ 17 typedef char dataType; /*define the data type of the vertex value*/ 18 19 /*define the data structure of the Edge*/ 20 typedef struct eNode *ptrToENode; 21 typedef struct eNode { 22 vertex v1, v2; /*two vertex between the edge <v1,v2>*/ 23 weightType weight; /*the value of the edge's weight */ 24 }; 25 typedef ptrToENode edge; 26 27 /*==================A adjacent link to describe a graph=========================================*/ 28 /*define the data structure adjacent table node*/ 29 typedef struct adjNode *ptrToAdjNode; 30 typedef struct adjNode { 31 vertex adjVerx; /*the index of the vertex*/ 32 weightType weight; /*the value of the weight*/ 33 ptrToAdjNode next; /*the point to point the next node*/ 34 }; 35 36 /*define the data structure of the adjacent head*/ 37 typedef struct vNode *ptrToVNode; 38 typedef struct vNode { 39 ptrToAdjNode head; /*the point to point the adjacent table node*/ 40 dataType data; /*the space to store the name of the vertex,but some time the vertex has no names*/ 41 } adjList[MAX_VERTEX_NUM]; 42 43 /*define the data structure of graph*/ 44 typedef struct gLNode *ptrTogLNode; 45 typedef struct gLNode { 46 int vertex_number; /*the number of the vertex*/ 47 int edge_nunber; /*the number of the edge*/ 48 adjList g; /*adjacent table*/ 49 }; 50 typedef ptrTogLNode adjacentTableGraph; /*a graph show by adjacent table*/ 51 52 /* 53 create a graph given the vertex number. 54 @param vertexNum The verter number of the graph 55 @return a graph with vertex but no any egdgs 56 */ 57 adjacentTableGraph createLGraph(int vertexNum) { 58 adjacentTableGraph graph; 59 60 vertex v; 61 graph = (adjacentTableGraph) malloc(sizeof(struct gLNode)); 62 graph->vertex_number = vertexNum; 63 graph->edge_nunber = 0; 64 /*initialize the adjacent table*/ 65 for (v = 0; v < graph->vertex_number; v++) { 66 graph->g[v].head = NULL; 67 } 68 return graph; 69 } 70 71 /* 72 insert a edge to graph.We will distinct oriented graph and undirected graph 73 The e->v1 and e->v2 are the vertexs' indexs in the adjacent table 74 @param graph The graph you want to insert edge 75 @param e The edge you want to insert the graph 76 @param isOriented Whether the graph is oriented graph.If the graph is oriented 77 we will set adjacent table graph[v1]->head=v2 and set graph[v1].head=v2 78 otherwise we only set graph[v1].head=v2 79 */ 80 void insertEdgeToLink(adjacentTableGraph graph, edge e, int isOriented) { 81 /*build node<v1,v2>*/ 82 ptrToAdjNode newNode; 83 newNode = (ptrToAdjNode) malloc(sizeof(struct adjNode)); 84 newNode->adjVerx = e->v2; 85 newNode->weight = e->weight; 86 newNode->next = graph->g[e->v1].head; 87 graph->g[e->v1].head = newNode; 88 /*if the graph is directed graph*/ 89 if (!isOriented) { 90 newNode = (ptrToAdjNode) malloc(sizeof(struct adjNode)); 91 newNode->adjVerx = e->v1; 92 newNode->weight = e->weight; 93 newNode->next = graph->g[e->v2].head; 94 graph->g[e->v2].head = newNode; 95 } 96 } 97 98 /* 99 build a graph stored by adjacent table 100 */ 101 adjacentTableGraph buildLGraph(int isOrdered) { 102 adjacentTableGraph graph; 103 edge e; 104 vertex i; 105 int vertex_num; 106 107 scanf("%d", &vertex_num); 108 graph = createLGraph(vertex_num); 109 scanf("%d", &(graph->edge_nunber)); 110 if (graph->edge_nunber) { 111 e = (edge) malloc(sizeof(struct eNode)); 112 for (i = 0; i < graph->edge_nunber; i++) { 113 scanf("%d %d %d", &e->v1, &e->v2, &e->weight); 114 e->v1--; 115 e->v2--; 116 insertEdgeToLink(graph, e, isOrdered); 117 } 118 } 119 120 return graph; 121 } 122 123 /*----------------------define collection and some operator of graph's nodes-----------------------------*/ 124 125 /* 126 * The element of collection 127 */ 128 typedef vertex elementType; 129 130 /* 131 * The index of root element,we use it as the collection name 132 */ 133 typedef vertex setName; 134 135 /* 136 * A array to store the collection,we set the 137 * first index is 0 138 */ 139 typedef elementType setType[MAX_VERTEX_NUM]; 140 141 /* 142 * Initialize collection 143 * @param A <code>elementType</code> array to store the collections,maybe 144 * many collection will be stored in this array 145 * @param n The length of the collection 146 */ 147 void initializeVSet(setType s, int n) { 148 elementType x; 149 for (x = 0; x < n; x++) { 150 s[x] = -1; 151 } 152 } 153 154 /* 155 * Union two collections which is showed by root element.We will union smaller collection 156 * to greater collection and we will update the quantity for greater collection 157 * @param s A <code>elementType</code> array to store the collections,maybe 158 * many collection will be stored in this array 159 * @param root1 The root element of the first collection 160 * @param root2 The root element of the second collection 161 */ 162 void unionCollection(setType s, setName root1, setName root2) { 163 /* 164 * If root2's quantity greater than root1 165 */ 166 if (s[root2] < s[root1]) { 167 s[root2] += s[root1]; 168 s[root1] = root2; 169 } else { 170 s[root1] += s[root2]; 171 s[root2] = root1; 172 } 173 } 174 175 /* 176 * Find the element in which collection and use the root element 177 * to represent this collection and return it.In this method,we will compress path 178 * @param s A <code>elementType</code> array to store the collections,maybe 179 * many collection will be stored in this array 180 * @param x The element we find which collection it in. 181 */ 182 setName find(setType s, elementType x) { 183 if (s[x] < 0) { 184 return x; 185 } else { 186 /* 187 *compress path 188 */ 189 return s[x] = find(s, s[x]); 190 } 191 } 192 193 /* 194 * Check v1 and v1 whether is belong to a same collection. If not union these 195 * two collection,otherwise do nothing. 196 * @param vSet A <code>elementType</code> array to store the collections,maybe 197 * many collection will be stored in this array 198 * @param v1 The index of node in the graph,also the element is the collection. 199 * @param v2 The index of node in the graph,also the element is the collection. 200 * @return If the two element is belong same collection,union them and return 1 201 * else do nothing and return 0; 202 */ 203 int checkCircle(setType vSet, vertex v1, vertex v2) { 204 setName root1 = find(vSet, v1); 205 setName root2 = find(vSet, v2); 206 if (root1 == root2) { 207 return 0; 208 } else { 209 unionCollection(vSet, root1, root2); 210 return 1; 211 } 212 } 213 214 /*-------------define the minimal heap of edge-------------------*/ 215 216 /* 217 * Update the tree whose root element index is p into minimal heap,we use the edgs's 218 * weight as the to construct the minimal heap. 219 * 220 * @param eset A array of edge to store the heap,because the edge is point variable 221 * So the eSet is a edge type array,you can compare it with <code>int* arr</code> 222 * @param The index of the root element. 223 * @param n The length of the heap,the max index is n-1 in this case. And 224 * this heap index is start from zero. 225 */ 226 void percDowm(edge eSet, int p, int n) { 227 int parent, child; 228 struct eNode x; 229 230 x = eSet[p]; 231 for (parent = p; (parent * 2 + 1) < n; parent = child) { 232 /* 233 * Because the first index if from zero,so the left child 234 * is parent*2+1 235 */ 236 child = parent * 2 + 1; 237 /* 238 * Find smaller weigh between the left child and right child 239 */ 240 if ((child != n - 1) && eSet[child].weight > eSet[child + 1].weight) { 241 child++; 242 } 243 if (x.weight <= eSet[child].weight) { 244 break; 245 } else { 246 eSet[parent] = eSet[child]; 247 } 248 } 249 eSet[parent] = x; 250 } 251 252 /* 253 * Initialize eSet heap and update it to be the minimal heap 254 * @param graph A graph which is stored by adjacent list 255 * @param eSet A array of the edge as the minimal heap 256 */ 257 void initializeESet(adjacentTableGraph graph, edge eSet) { 258 vertex v; 259 ptrToAdjNode w; 260 int counter = 0; 261 for (v = 0; v < graph->vertex_number; v++) { 262 for (w = graph->g[v].head; w; w = w->next) { 263 /* 264 * expect for put same edge to it,we only 265 * put <v1,v2> to it. 266 */ 267 if (v < w->adjVerx) { 268 eSet[counter].v1 = v; 269 eSet[counter].v2 = w->adjVerx; 270 eSet[counter].weight = w->weight; 271 counter++; 272 } 273 274 } 275 } 276 /* 277 * Initialize the minimal heap 278 */ 279 for (counter = graph->edge_nunber / 2; counter >= 0; counter--) { 280 percDowm(eSet, counter, graph->edge_nunber); 281 } 282 } 283 284 /* 285 * Get minimal edge from the minimal weight heap 286 * @param eset A array of edge to store the heap,because the edge is point variable 287 * So the eSet is a edge type array,you can compare it with <code>int* arr</code> 288 * @param The current size of the minimal heap 289 * @return The index of the minimal edge in this heap(array) 290 */ 291 int getEdge(edge eSet, int currentSize) { 292 if (currentSize == 0) { 293 return currentSize - 1; 294 } 295 struct eNode temp = eSet[currentSize - 1]; 296 eSet[currentSize - 1] = eSet[0]; 297 eSet[0] = temp; 298 percDowm(eSet, 0, currentSize - 1); 299 return currentSize - 1; 300 } 301 302 /* 303 * Implement the kruskal algorithms to find the minimal created tree 304 * Algorithms thought:we choose the minimal edge from graph but don't 305 * construct a circle each time. Until we choose the V-1 edges. The V 306 * is equal with the quantity of the graph's vertex 307 * In this program,we will use a counter to record the quantity of edges 308 * At last of this method,if we check the quantity of the edge is less than 309 * V-1, it indicates the graph is not collected,so -1 will be return,otherwise we will return 310 * the minimal created tree total weight. 311 * @param graph A graph which is stored by adjacent list 312 * @param mst A A graph which is stored by adjacent list to store the minimal created tree 313 * @return If the graph is collected,the weight of the minimal created tree 314 * will be return, otherwise return -1 315 */ 316 int kruskal(adjacentTableGraph graph, adjacentTableGraph mst) { 317 /* 318 * totalWeight is to record the total weight 319 * of the minimal created tree 320 */ 321 weightType totalWeight; 322 /* 323 * eCounter is to record the quantity of edges which has been 324 * insert the <code>mst<code> 325 * 326 * nextEdge is to record the next minimal edge in the minimal heap 327 */ 328 int eCounter, nextEdge; 329 330 /* 331 *A set of the vertex to store the vertex and implement 332 *some operation such as union find and so on 333 */ 334 setType vSet; 335 336 /* 337 * A array of edge to as the minimal heap to store the egdes 338 */ 339 edge eSet; 340 341 /* 342 * Initialize some variables 343 */ 344 initializeVSet(vSet, graph->vertex_number); 345 eSet = (edge) malloc((sizeof(struct eNode)) * (graph->edge_nunber)); 346 initializeESet(graph, eSet); 347 // mst = createLGraph(graph->vertex_number); 348 totalWeight = 0; 349 eCounter = 0; 350 nextEdge = graph->edge_nunber; 351 while (eCounter < graph->vertex_number - 1) { 352 nextEdge = getEdge(eSet, nextEdge); 353 if (nextEdge < 0) { 354 break; 355 } 356 /* 357 * Check whether a circle between two vertex 358 */ 359 if (checkCircle(vSet, eSet[nextEdge].v1, eSet[nextEdge].v2)) { 360 insertEdgeToLink(mst, eSet + nextEdge, 0); 361 totalWeight += eSet[nextEdge].weight; 362 eCounter++; 363 } 364 } 365 if (eCounter < graph->vertex_number - 1) { 366 totalWeight = -1; 367 } 368 return totalWeight; 369 } 370 371 /*========Use DFS to print the result of the minimal created tree==========*/ 372 /* 373 * A method to access graph 374 */ 375 void visit(adjacentTableGraph graph, vertex v) { 376 printf("%d ", v); 377 } 378 379 /* 380 Depth first search a graph 381 @param graph The graph need to search 382 @param startPoint The fisrt point we start search the graph 383 @paran int *visited The array we use to tag the vertex we has accessed. 384 */ 385 void DFS(adjacentTableGraph graph, vertex startPoint, int *visited) { 386 ptrToAdjNode p; 387 visit(graph, startPoint); 388 p = graph->g[3].head; 389 visited[startPoint] = 1; 390 for (p = graph->g[startPoint].head; p; p = p->next) { 391 if (visited[p->adjVerx] == 0) { 392 DFS(graph, p->adjVerx, visited); 393 } 394 } 395 } 396 397 /* 398 * Initialize a visited array that make them all to zero 399 */ 400 void initVisited(int length, int *visited) { 401 int i; 402 for (i = 0; i < length; i++) { 403 visited[i] = 0; 404 } 405 } 406 407 int main() { 408 adjacentTableGraph graph = buildLGraph(0); 409 adjacentTableGraph mst = createLGraph(graph->vertex_number); 410 vertex visited[graph->vertex_number]; 411 weightType totalWeight = kruskal(graph, mst); 412 printf("%d\n", totalWeight); 413 /*initVisited(graph->vertex_number, visited); 414 DFS(mst, 0, visited);*/ 415 return 0; 416 }