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

本博客的代码的思想和图片参考:好大学慕课浙江大学陈越老师、何钦铭老师的《数据结构》

1 最小生成树的概念

最小生成树的概念:是由图生成而来的

是一棵树

1.无回路

2.如果有V个定点就有V-1条边

是生成树

1.包含图中所有的节点V

2.V-1条边都在图里面

3.边的权重和最小。

4.向生成树中添加任意一条边都构成回路。


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 15
1 2 5
1 3 3
1 4 7
1 5 4
1 6 2
2 3 4
2 4 6
2 5 2
2 6 6
3 4 6
3 5 1
3 6 1
4 5 10
4 6 8
5 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

 

posted @ 2017-05-15 20:54  浪漫逆风  阅读(11767)  评论(0编辑  收藏  举报