最小生成樹之Prim算法和Kruskal算法

本博客的代碼的思想和圖片參考:好大學慕課浙江大學陳越老師、何欽銘老師的《數據結構》node

1 最小生成樹的概念

最小生成樹的概念:是由圖生成而來的git

是一棵樹算法

1.無迴路數據結構

2.若是有V個定點就有V-1條邊less

是生成樹ide

1.包含圖中全部的節點V測試

2.V-1條邊都在圖裏面ui

3.邊的權重和最小。this

4.向生成樹中添加任意一條邊都構成迴路。spa


2 算法思想:貪心算法

「貪」:每一步都要最好的。

「好」:權重最小的邊

約束條件:

1.只能使用圖裏面的邊

2.只能正好使用V-1條邊

3.不能有迴路


3 Prim算法—讓一棵小樹慢慢長大

3.1算法思想:

1.先選擇一個頂點做爲樹的根節點,把這個根節點當成一棵樹

2.選擇圖中距離這棵樹最近可是沒有被樹收錄的一個頂點,把他收錄在樹中,而且保證不構成迴路

3.按照這樣的方法,把全部的圖的頂點一一收錄進樹中。

4.若是沒有頂點能夠收錄

a.若是圖中的頂點數量等於樹的頂點數量-->最小生成樹構造完成

b. 若是圖中的頂點數量不等於樹的頂點數量-->此圖不連通

下面使用圖片來具體描述此算法的算法思想:


 3.2Prim算法的僞代碼描述

經過咱們對算法的描述,咱們發現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).此種算法對於稠密圖比較適用。

 

4 Kruskal 算法—將樹合併成森林

4.1 算法思想

使用貪心算法,每次獲取權重最小的邊,可是不能讓生成樹構成迴路。直到去到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算法差很少



5 習題

下面經過一道練習題來比較Prim算法和Kruskal算法的優劣

題目的PTA連接

https://pta.patest.cn/pta/test/3512/exam/4/question/85491

題目內容:

5.1題目內容:

現有村落間道路的統計數據表中,列出了有可能建設成標準公路的若干條道路的成本,求使每一個村落都有公路連通所須要的最低成本。

輸入格式:

輸入數據包括城鎮數目正整數N(≤1000)和候選道路數目M(≤3N);隨後的M行對應M條道路,每行給出3個正整數,分別是該條道路直接連通的兩個城鎮的編號以及該道路改建的預算成本。爲簡單起見,城鎮從1N編號。

輸出格式:

輸出村村通須要的最低成本。若是輸入數據不足以保證暢通,則輸出−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

代碼能夠在最後的連接裏面



5.2 比較Prim算法和Kruskal算法

上面的習題其實很簡單,就是Prim算法和Kruskal算法的應用。很簡單,只須要改一下輸出便可。

Prim算法在PTA的運行結果:



Kruskal算法在PTA的運行結果:

 

5.2.1空間複雜的比較

從內存的使用狀況來看,Prim算法使用的鄰接矩陣來存儲圖,Kruskal算法使用鄰接表來存儲圖,從圖中能夠看出,鄰接矩陣在最N時內存由1M增加到8M,而鄰接表的內存始終是在1M。因而可知在同等的數據量的狀況下,鄰接表比鄰接矩陣更加節省內存空間。

5.2.2 時間複雜的比較

就本題的測試結果來看,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 }
Prim_Base

測試數據和運行結果:

 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 
Prime_Base_testData And result

 

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 }
Kruska_Base

測試數據和運行結果

 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_Base_testData And result

 

上面村村通習題的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 }
valige_path_peim

上面村村通習題的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 }
valige_path_kruskal
相關文章
相關標籤/搜索