最小生成树之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个正整数,分别是该条道路直接连通的两个城镇的编号以及该道路改建的预算成本。为简单起见,城镇从1到N编号。
输出格式:
输出村村通需要的最低成本。如果输入数据不足以保证畅通,则输出−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 }
测试数据和运行结果:
1 7 12 2 1 2 2 3 1 4 1 4 2 5 10 5 2 4 3 6 3 1 4 7 3 6 5 8 4 3 2 9 4 6 8 10 4 7 4 11 4 5 7 12 5 7 6 13 7 6 1 14 15 Test result: 16 totalWeigh:16 17 0 1 3 6 4 5 2
Kruskal算法求最小生成树的权重和打印路径代码:
1 /* 2 * kruskal.c 3 * 4 * Created on: 2017年5月15日 5 * Author: ygh 6 */ 7 8 #include <stdio.h> 9 #include <stdlib.h> 10 11 #define MAX_VERTEX_NUM 10001 /*define the max number of the vertex*/ 12 #define INFINITY 65535 /*define double byte no negitive integer max number is 65535*/ 13 #define ERROR -1 14 15 typedef int vertex; /*define the data type of the vertex*/ 16 typedef int weightType; /*define the data type of the weight*/ 17 typedef char dataType; /*define the data type of the vertex value*/ 18 19 /*define the data structure of the Edge*/ 20 typedef struct eNode *ptrToENode; 21 typedef struct eNode { 22 vertex v1, v2; /*two vertex between the edge <v1,v2>*/ 23 weightType weight; /*the value of the edge's weight */ 24 }; 25 typedef ptrToENode edge; 26 27 /*==================A adjacent link to describe a graph=========================================*/ 28 /*define the data structure adjacent table node*/ 29 typedef struct adjNode *ptrToAdjNode; 30 typedef struct adjNode { 31 vertex adjVerx; /*the index of the vertex*/ 32 weightType weight; /*the value of the weight*/ 33 ptrToAdjNode next; /*the point to point the next node*/ 34 }; 35 36 /*define the data structure of the adjacent head*/ 37 typedef struct vNode *ptrToVNode; 38 typedef struct vNode { 39 ptrToAdjNode head; /*the point to point the adjacent table node*/ 40 dataType data; /*the space to store the name of the vertex,but some time the vertex has no names*/ 41 } adjList[MAX_VERTEX_NUM]; 42 43 /*define the data structure of graph*/ 44 typedef struct gLNode *ptrTogLNode; 45 typedef struct gLNode { 46 int vertex_number; /*the number of the vertex*/ 47 int edge_nunber; /*the number of the edge*/ 48 adjList g; /*adjacent table*/ 49 }; 50 typedef ptrTogLNode adjacentTableGraph; /*a graph show by adjacent table*/ 51 52 /* 53 create a graph given the vertex number. 54 @param vertexNum The verter number of the graph 55 @return a graph with vertex but no any egdgs 56 */ 57 adjacentTableGraph createLGraph(int vertexNum) { 58 adjacentTableGraph graph; 59 60 vertex v; 61 graph = (adjacentTableGraph) malloc(sizeof(struct gLNode)); 62 graph->vertex_number = vertexNum; 63 graph->edge_nunber = 0; 64 /*initialize the adjacent table*/ 65 for (v = 0; v < graph->vertex_number; v++) { 66 graph->g[v].head = NULL; 67 } 68 return graph; 69 } 70 71 /* 72 insert a edge to graph.We will distinct oriented graph and undirected graph 73 The e->v1 and e->v2 are the vertexs' indexs in the adjacent table 74 @param graph The graph you want to insert edge 75 @param e The edge you want to insert the graph 76 @param isOriented Whether the graph is oriented graph.If the graph is oriented 77 we will set adjacent table graph[v1]->head=v2 and set graph[v1].head=v2 78 otherwise we only set graph[v1].head=v2 79 */ 80 void insertEdgeToLink(adjacentTableGraph graph, edge e, int isOriented) { 81 /*build node<v1,v2>*/ 82 ptrToAdjNode newNode; 83 newNode = (ptrToAdjNode) malloc(sizeof(struct adjNode)); 84 newNode->adjVerx = e->v2; 85 newNode->weight = e->weight; 86 newNode->next = graph->g[e->v1].head; 87 graph->g[e->v1].head = newNode; 88 /*if the graph is directed graph*/ 89 if (!isOriented) { 90 newNode = (ptrToAdjNode) malloc(sizeof(struct adjNode)); 91 newNode->adjVerx = e->v1; 92 newNode->weight = e->weight; 93 newNode->next = graph->g[e->v2].head; 94 graph->g[e->v2].head = newNode; 95 } 96 } 97 98 /* 99 build a graph stored by adjacent table 100 */ 101 adjacentTableGraph buildLGraph(int isOrdered) { 102 adjacentTableGraph graph; 103 edge e; 104 vertex i; 105 int vertex_num; 106 107 scanf("%d", &vertex_num); 108 graph = createLGraph(vertex_num); 109 scanf("%d", &(graph->edge_nunber)); 110 if (graph->edge_nunber) { 111 e = (edge) malloc(sizeof(struct eNode)); 112 for (i = 0; i < graph->edge_nunber; i++) { 113 scanf("%d %d %d", &e->v1, &e->v2, &e->weight); 114 e->v1--; 115 e->v2--; 116 insertEdgeToLink(graph, e, isOrdered); 117 } 118 } 119 120 return graph; 121 } 122 123 /*----------------------define collection and some operator of graph's nodes-----------------------------*/ 124 125 /* 126 * The element of collection 127 */ 128 typedef vertex elementType; 129 130 /* 131 * The index of root element,we use it as the collection name 132 */ 133 typedef vertex setName; 134 135 /* 136 * A array to store the collection,we set the 137 * first index is 0 138 */ 139 typedef elementType setType[MAX_VERTEX_NUM]; 140 141 /* 142 * Initialize collection 143 * @param A <code>elementType</code> array to store the collections,maybe 144 * many collection will be stored in this array 145 * @param n The length of the collection 146 */ 147 void initializeVSet(setType s, int n) { 148 elementType x; 149 for (x = 0; x < n; x++) { 150 s[x] = -1; 151 } 152 } 153 154 /* 155 * Union two collections which is showed by root element.We will union smaller collection 156 * to greater collection and we will update the quantity for greater collection 157 * @param s A <code>elementType</code> array to store the collections,maybe 158 * many collection will be stored in this array 159 * @param root1 The root element of the first collection 160 * @param root2 The root element of the second collection 161 */ 162 void unionCollection(setType s, setName root1, setName root2) { 163 /* 164 * If root2's quantity greater than root1 165 */ 166 if (s[root2] < s[root1]) { 167 s[root2] += s[root1]; 168 s[root1] = root2; 169 } else { 170 s[root1] += s[root2]; 171 s[root2] = root1; 172 } 173 } 174 175 /* 176 * Find the element in which collection and use the root element 177 * to represent this collection and return it.In this method,we will compress path 178 * @param s A <code>elementType</code> array to store the collections,maybe 179 * many collection will be stored in this array 180 * @param x The element we find which collection it in. 181 */ 182 setName find(setType s, elementType x) { 183 if (s[x] < 0) { 184 return x; 185 } else { 186 /* 187 *compress path 188 */ 189 return s[x] = find(s, s[x]); 190 } 191 } 192 193 /* 194 * Check v1 and v1 whether is belong to a same collection. If not union these 195 * two collection,otherwise do nothing. 196 * @param vSet A <code>elementType</code> array to store the collections,maybe 197 * many collection will be stored in this array 198 * @param v1 The index of node in the graph,also the element is the collection. 199 * @param v2 The index of node in the graph,also the element is the collection. 200 * @return If the two element is belong same collection,union them and return 1 201 * else do nothing and return 0; 202 */ 203 int checkCircle(setType vSet, vertex v1, vertex v2) { 204 setName root1 = find(vSet, v1); 205 setName root2 = find(vSet, v2); 206 if (root1 == root2) { 207 return 0; 208 } else { 209 unionCollection(vSet, root1, root2); 210 return 1; 211 } 212 } 213 214 /*-------------define the minimal heap of edge-------------------*/ 215 216 /* 217 * Update the tree whose root element index is p into minimal heap,we use the edgs's 218 * weight as the to construct the minimal heap. 219 * 220 * @param eset A array of edge to store the heap,because the edge is point variable 221 * So the eSet is a edge type array,you can compare it with <code>int* arr</code> 222 * @param The index of the root element. 223 * @param n The length of the heap,the max index is n-1 in this case. And 224 * this heap index is start from zero. 225 */ 226 void percDowm(edge eSet, int p, int n) { 227 int parent, child; 228 struct eNode x; 229 230 x = eSet[p]; 231 for (parent = p; (parent * 2 + 1) < n; parent = child) { 232 /* 233 * Because the first index if from zero,so the left child 234 * is parent*2+1 235 */ 236 child = parent * 2 + 1; 237 /* 238 * Find smaller weigh between the left child and right child 239 */ 240 if ((child != n - 1) && eSet[child].weight > eSet[child + 1].weight) { 241 child++; 242 } 243 if (x.weight <= eSet[child].weight) { 244 break; 245 } else { 246 eSet[parent] = eSet[child]; 247 } 248 } 249 eSet[parent] = x; 250 } 251 252 /* 253 * Initialize eSet heap and update it to be the minimal heap 254 * @param graph A graph which is stored by adjacent list 255 * @param eSet A array of the edge as the minimal heap 256 */ 257 void initializeESet(adjacentTableGraph graph, edge eSet) { 258 vertex v; 259 ptrToAdjNode w; 260 int counter = 0; 261 for (v = 0; v < graph->vertex_number; v++) { 262 for (w = graph->g[v].head; w; w = w->next) { 263 /* 264 * expect for put same edge to it,we only 265 * put <v1,v2> to it. 266 */ 267 if (v < w->adjVerx) { 268 eSet[counter].v1 = v; 269 eSet[counter].v2 = w->adjVerx; 270 eSet[counter].weight = w->weight; 271 counter++; 272 } 273 274 } 275 } 276 /* 277 * Initialize the minimal heap 278 */ 279 for (counter = graph->edge_nunber / 2; counter >= 0; counter--) { 280 percDowm(eSet, counter, graph->edge_nunber); 281 } 282 } 283 284 /* 285 * Get minimal edge from the minimal weight heap 286 * @param eset A array of edge to store the heap,because the edge is point variable 287 * So the eSet is a edge type array,you can compare it with <code>int* arr</code> 288 * @param The current size of the minimal heap 289 * @return The index of the minimal edge in this heap(array) 290 */ 291 int getEdge(edge eSet, int currentSize) { 292 if (currentSize == 0) { 293 return currentSize - 1; 294 } 295 struct eNode temp = eSet[currentSize - 1]; 296 eSet[currentSize - 1] = eSet[0]; 297 eSet[0] = temp; 298 percDowm(eSet, 0, currentSize - 1); 299 return currentSize - 1; 300 } 301 302 /* 303 * Implement the kruskal algorithms to find the minimal created tree 304 * Algorithms thought:we choose the minimal edge from graph but don't 305 * construct a circle each time. Until we choose the V-1 edges. The V 306 * is equal with the quantity of the graph's vertex 307 * In this program,we will use a counter to record the quantity of edges 308 * At last of this method,if we check the quantity of the edge is less than 309 * V-1, it indicates the graph is not collected,so -1 will be return,otherwise we will return 310 * the minimal created tree total weight. 311 * @param graph A graph which is stored by adjacent list 312 * @param mst A A graph which is stored by adjacent list to store the minimal created tree 313 * @return If the graph is collected,the weight of the minimal created tree 314 * will be return, otherwise return -1 315 */ 316 int kruskal(adjacentTableGraph graph, adjacentTableGraph mst) { 317 /* 318 * totalWeight is to record the total weight 319 * of the minimal created tree 320 */ 321 weightType totalWeight; 322 /* 323 * eCounter is to record the quantity of edges which has been 324 * insert the <code>mst<code> 325 * 326 * nextEdge is to record the next minimal edge in the minimal heap 327 */ 328 int eCounter, nextEdge; 329 330 /* 331 *A set of the vertex to store the vertex and implement 332 *some operation such as union find and so on 333 */ 334 setType vSet; 335 336 /* 337 * A array of edge to as the minimal heap to store the egdes 338 */ 339 edge eSet; 340 341 /* 342 * Initialize some variables 343 */ 344 initializeVSet(vSet, graph->vertex_number); 345 eSet = (edge) malloc((sizeof(struct eNode)) * (graph->edge_nunber)); 346 initializeESet(graph, eSet); 347 // mst = createLGraph(graph->vertex_number); 348 totalWeight = 0; 349 eCounter = 0; 350 nextEdge = graph->edge_nunber; 351 while (eCounter < graph->vertex_number - 1) { 352 nextEdge = getEdge(eSet, nextEdge); 353 if (nextEdge < 0) { 354 break; 355 } 356 /* 357 * Check whether a circle between two vertex 358 */ 359 if (checkCircle(vSet, eSet[nextEdge].v1, eSet[nextEdge].v2)) { 360 insertEdgeToLink(mst, eSet + nextEdge, 0); 361 totalWeight += eSet[nextEdge].weight; 362 eCounter++; 363 } 364 } 365 if (eCounter < graph->vertex_number - 1) { 366 totalWeight = -1; 367 } 368 return totalWeight; 369 } 370 371 /*========Use DFS to print the result of the minimal created tree==========*/ 372 /* 373 * A method to access graph 374 */ 375 void visit(adjacentTableGraph graph, vertex v) { 376 printf("%d ", v); 377 } 378 379 /* 380 Depth first search a graph 381 @param graph The graph need to search 382 @param startPoint The fisrt point we start search the graph 383 @paran int *visited The array we use to tag the vertex we has accessed. 384 */ 385 void DFS(adjacentTableGraph graph, vertex startPoint, int *visited) { 386 ptrToAdjNode p; 387 visit(graph, startPoint); 388 p = graph->g[3].head; 389 visited[startPoint] = 1; 390 for (p = graph->g[startPoint].head; p; p = p->next) { 391 if (visited[p->adjVerx] == 0) { 392 DFS(graph, p->adjVerx, visited); 393 } 394 } 395 } 396 397 /* 398 * Initialize a visited array that make them all to zero 399 */ 400 void initVisited(int length, int *visited) { 401 int i; 402 for (i = 0; i < length; i++) { 403 visited[i] = 0; 404 } 405 } 406 407 int main() { 408 adjacentTableGraph graph = buildLGraph(0); 409 adjacentTableGraph mst = createLGraph(graph->vertex_number); 410 vertex visited[graph->vertex_number]; 411 weightType totalWeight = kruskal(graph, mst); 412 printf("totalWeight:%d\n", totalWeight); 413 initVisited(graph->vertex_number, visited); 414 DFS(mst, 0, visited); 415 return 0; 416 }
测试数据和运行结果
1 7 12 2 1 2 2 3 1 4 1 4 2 5 10 5 2 4 3 6 3 1 4 7 3 6 5 8 4 3 2 9 4 6 8 10 4 7 4 11 4 5 7 12 5 7 6 13 7 6 1 14 15 Test result: 16 totalWeigh:16 17 0 1 3 6 4 5 2
上面村村通习题的Prim代码
1 /* 2 * path.c 3 * 4 * Created on: 2017年5月15日 5 * Author: ygh 6 */ 7 #include <stdio.h> 8 #include <stdlib.h> 9 10 #define MAX_VERTEX_NUM 10001 /*define the max number of the vertex*/ 11 #define INFINITY 65535 /*define double byte no negitive integer max number is 65535*/ 12 #define ERROR -1 13 14 typedef int vertex; /*define the data type of the vertex*/ 15 typedef int weightType; /*define the data type of the weight*/ 16 typedef char dataType; /*define the data type of the vertex value*/ 17 18 /*define the data structure of the Edge*/ 19 typedef struct eNode *ptrToENode; 20 typedef struct eNode { 21 vertex v1, v2; /*two vertex between the edge <v1,v2>*/ 22 weightType weight; /*the value of the edge's weight */ 23 }; 24 typedef ptrToENode edge; 25 26 /*==================A adjacent matrix to describe a graph=========================================*/ 27 28 /*define the data structure of the graph*/ 29 typedef struct gMNode *ptrTogMNode; 30 typedef struct gMNode { 31 int vertex_number; /*the number of the vertex*/ 32 int edge_nunber; /*the number of the edge*/ 33 weightType g[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; /*define the adjacent matrix weight of graph*/ 34 dataType data[MAX_VERTEX_NUM]; /*define the dataType array to store the value of vertex*/ 35 }; 36 typedef ptrTogMNode adjacentMatrixGraph; /*a graph show by adjacent matrix*/ 37 38 /* 39 create a graph given the vertex number. 40 @param vertexNum The verter number of the graph 41 @return a graph with vertex but no any egdgs 42 */ 43 adjacentMatrixGraph createMGraph(int vertexNum) { 44 vertex v, w; 45 adjacentMatrixGraph graph; 46 graph = (adjacentMatrixGraph) malloc(sizeof(struct gMNode)); 47 graph->vertex_number = vertexNum; 48 graph->edge_nunber = 0; 49 /*initialize the adjacent matrix*/ 50 for (v = 0; v < graph->vertex_number; v++) { 51 for (w = 0; w < graph->vertex_number; w++) { 52 graph->g[v][w] = INFINITY; 53 } 54 } 55 56 return graph; 57 } 58 59 /* 60 insert a edge to graph.We will distinct oriented graph and undirected graph 61 @param graph The graph you want to insert edge 62 @param e The edge you want to insert the graph 63 @param isOriented Whether the graph is oriented graph.If the graph is oriented 64 we will set adjacent matrix [n][m]=[m][n]=edge's weight,else we only set 65 the adjacent matrix [n][m]=edge's weight 66 */ 67 void inserEdgeToMatrix(adjacentMatrixGraph graph, edge e, int isOriented) { 68 graph->g[e->v1][e->v2] = e->weight; 69 if (!isOriented) { 70 graph->g[e->v2][e->v1] = e->weight; 71 } 72 } 73 74 /* 75 construct a graph according user's input 76 77 @return a graph has been filled good 78 */ 79 adjacentMatrixGraph buildMGraph(int isOrdered) { 80 adjacentMatrixGraph graph; 81 edge e; 82 vertex i; 83 int vertex_num; 84 scanf("%d", &vertex_num); 85 graph = createMGraph(vertex_num); 86 scanf("%d", &(graph->edge_nunber)); 87 if (graph->edge_nunber) { 88 e = (edge) malloc(sizeof(struct eNode)); 89 for (i = 0; i < graph->edge_nunber; i++) { 90 scanf("%d %d %d", &e->v1, &e->v2, &e->weight); 91 e->v1--; 92 e->v2--; 93 inserEdgeToMatrix(graph, e, isOrdered); 94 } 95 } 96 return graph; 97 98 } 99 100 /*==================A adjacent link to describe a graph=========================================*/ 101 /*define the data structure adjacent table node*/ 102 typedef struct adjNode *ptrToAdjNode; 103 typedef struct adjNode { 104 vertex adjVerx; /*the index of the vertex*/ 105 weightType weight; /*the value of the weight*/ 106 ptrToAdjNode next; /*the point to point the next node*/ 107 }; 108 109 /*define the data structure of the adjacent head*/ 110 typedef struct vNode *ptrToVNode; 111 typedef struct vNode { 112 ptrToAdjNode head; /*the point to point the adjacent table node*/ 113 dataType data; /*the space to store the name of the vertex,but some time the vertex has no names*/ 114 } adjList[MAX_VERTEX_NUM]; 115 116 /*define the data structure of graph*/ 117 typedef struct gLNode *ptrTogLNode; 118 typedef struct gLNode { 119 int vertex_number; /*the number of the vertex*/ 120 int edge_nunber; /*the number of the edge*/ 121 adjList g; /*adjacent table*/ 122 }; 123 typedef ptrTogLNode adjacentTableGraph; /*a graph show by adjacent table*/ 124 125 /* 126 create a graph given the vertex number. 127 @param vertexNum The verter number of the graph 128 @return a graph with vertex but no any egdgs 129 */ 130 adjacentTableGraph createLGraph(int vertexNum) { 131 adjacentTableGraph graph; 132 133 vertex v; 134 graph = (adjacentTableGraph) malloc(sizeof(struct gLNode)); 135 graph->vertex_number = vertexNum; 136 graph->edge_nunber = 0; 137 /*initialize the adjacent table*/ 138 for (v = 0; v < graph->vertex_number; v++) { 139 graph->g[v].head = NULL; 140 } 141 return graph; 142 } 143 144 /* 145 insert a edge to graph.We will distinct oriented graph and undirected graph 146 The e->v1 and e->v2 are the vertexs' indexs in the adjacent table 147 @param graph The graph you want to insert edge 148 @param e The edge you want to insert the graph 149 @param isOriented Whether the graph is oriented graph.If the graph is oriented 150 we will set adjacent table graph[v1]->head=v2 and set graph[v1].head=v2 151 otherwise we only set graph[v1].head=v2 152 */ 153 void insertEdgeToLink(adjacentTableGraph graph, edge e, int isOriented) { 154 /*build node<v1,v2>*/ 155 ptrToAdjNode newNode; 156 newNode = (ptrToAdjNode) malloc(sizeof(struct adjNode)); 157 newNode->adjVerx = e->v2; 158 newNode->weight = e->weight; 159 newNode->next = graph->g[e->v1].head; 160 graph->g[e->v1].head = newNode; 161 /*if the graph is directed graph*/ 162 if (!isOriented) { 163 newNode = (ptrToAdjNode) malloc(sizeof(struct adjNode)); 164 newNode->adjVerx = e->v1; 165 newNode->weight = e->weight; 166 newNode->next = graph->g[e->v2].head; 167 graph->g[e->v2].head = newNode; 168 } 169 } 170 171 /* 172 build a graph stored by adjacent table 173 */ 174 adjacentTableGraph buildLGraph() { 175 adjacentTableGraph graph; 176 edge e; 177 vertex i; 178 int vertex_num; 179 180 scanf("%d", &vertex_num); 181 graph = createLGraph(vertex_num); 182 scanf("%d", &(graph->edge_nunber)); 183 if (graph->edge_nunber) { 184 e = (edge) malloc(sizeof(struct eNode)); 185 for (i = 0; i < graph->edge_nunber; i++) { 186 scanf("%d %d %d", &e->v1, &e->v2, &e->weight); 187 insertEdgeToLink(graph, e, 0); 188 } 189 } 190 191 return graph; 192 } 193 194 /* 195 * Find the minimal node closest to created tree 196 */ 197 vertex findMinDist(adjacentMatrixGraph graph, weightType dist[]) { 198 vertex minV, v; 199 weightType minDist = INFINITY; 200 for (v = 0; v < graph->vertex_number; v++) { 201 if (dist[v] != 0 && dist[v] < minDist) { 202 minDist = dist[v]; 203 minV = v; 204 } 205 } 206 if (minDist < INFINITY) { 207 return minV; 208 } else { 209 return ERROR; 210 } 211 } 212 213 /* 214 * Prim algorithms,we will store the minimal created tree with a adjacnet 215 * list table and return the minimal weight 216 * @param mGraph The graph showed by adjacent matrix is to store graph 217 * @param lGraph The graph showed by adjacent list is to store the minimal created tree 218 * @return The weight of the minimal created tree if the graph is connected, otherwise return 219 * <code>ERROR</code> 220 */ 221 int prim(adjacentMatrixGraph mGraph, adjacentTableGraph lGraph) { 222 223 weightType dist[mGraph->vertex_number], totalWeight; 224 vertex parent[mGraph->vertex_number], v, w; 225 int vCounter; 226 edge e; 227 228 /* 229 * Initialize dist and parent,default the start point is 0 index 230 */ 231 for (v = 0; v < mGraph->vertex_number; v++) { 232 dist[v] = mGraph->g[0][v]; 233 parent[v] = 0; 234 } 235 236 /* 237 * Initialize weight and vertex counter 238 */ 239 totalWeight = 0; 240 vCounter = 0; 241 /* 242 * Initialize a edge 243 */ 244 e = (edge) malloc(sizeof(struct eNode)); 245 246 /* 247 * Initialize dist[0] as the root of tree and set parent[0] to -1 248 */ 249 dist[0] = 0; 250 vCounter++; 251 parent[0] = -1; 252 /* 253 * Execute Prim algorithms 254 */ 255 while (1) { 256 v = findMinDist(mGraph, dist); 257 if (v == ERROR) { 258 break; 259 } 260 261 /* 262 * Put <v,parent[v]> to tree 263 */ 264 e->v1 = parent[v]; 265 e->v2 = v; 266 e->weight = dist[v]; 267 insertEdgeToLink(lGraph, e, 1); 268 totalWeight += dist[v]; 269 vCounter++; 270 dist[v] = 0; 271 272 /* 273 * Update the v adjacent vertex distance with minimal tree 274 */ 275 for (w = 0; w < mGraph->vertex_number; w++) { 276 /* 277 * If w is v adjacent vetex and not be added to minimal tree 278 */ 279 if (dist[w] != 0 && mGraph->g[v][w] < INFINITY) { 280 /* 281 * Update the distance to minimal created tree 282 */ 283 if (mGraph->g[v][w] < dist[w]) { 284 dist[w] = mGraph->g[v][w]; 285 parent[w] = v; 286 } 287 } 288 } 289 } 290 if (vCounter < mGraph->vertex_number) { 291 return ERROR; 292 } else { 293 return totalWeight; 294 } 295 } 296 297 /*========Use DFS to print the result of the minimal created tree==========*/ 298 /* 299 * A method to access graph 300 */ 301 void visit(adjacentTableGraph graph, vertex v) { 302 printf("%d ", v); 303 } 304 305 /* 306 Depth first search a graph 307 @param graph The graph need to search 308 @param startPoint The fisrt point we start search the graph 309 @paran int *visited The array we use to tag the vertex we has accessed. 310 */ 311 void DFS(adjacentTableGraph graph, vertex startPoint, int *visited) { 312 ptrToAdjNode p; 313 visit(graph, startPoint); 314 p = graph->g[3].head; 315 visited[startPoint] = 1; 316 for (p = graph->g[startPoint].head; p; p = p->next) { 317 if (visited[p->adjVerx] == 0) { 318 DFS(graph, p->adjVerx, visited); 319 } 320 } 321 } 322 323 /* 324 * Initialize a visited array that make them all to zero 325 */ 326 void initVisited(int length, int *visited) { 327 int i; 328 for (i = 0; i < length; i++) { 329 visited[i] = 0; 330 } 331 } 332 333 int main() { 334 adjacentTableGraph lGraph; 335 adjacentMatrixGraph mGraph = buildMGraph(0); 336 vertex visited[mGraph->vertex_number]; 337 lGraph = createLGraph(mGraph->vertex_number); 338 weightType totalWeigt = prim(mGraph, lGraph); 339 printf("%d\n", totalWeigt); 340 return 0; 341 }
上面村村通习题的Kruskal代码
1 /* 2 * kruskal.c 3 * 4 * Created on: 2017年5月15日 5 * Author: ygh 6 */ 7 8 #include <stdio.h> 9 #include <stdlib.h> 10 11 #define MAX_VERTEX_NUM 10001 /*define the max number of the vertex*/ 12 #define INFINITY 65535 /*define double byte no negitive integer max number is 65535*/ 13 #define ERROR -1 14 15 typedef int vertex; /*define the data type of the vertex*/ 16 typedef int weightType; /*define the data type of the weight*/ 17 typedef char dataType; /*define the data type of the vertex value*/ 18 19 /*define the data structure of the Edge*/ 20 typedef struct eNode *ptrToENode; 21 typedef struct eNode { 22 vertex v1, v2; /*two vertex between the edge <v1,v2>*/ 23 weightType weight; /*the value of the edge's weight */ 24 }; 25 typedef ptrToENode edge; 26 27 /*==================A adjacent link to describe a graph=========================================*/ 28 /*define the data structure adjacent table node*/ 29 typedef struct adjNode *ptrToAdjNode; 30 typedef struct adjNode { 31 vertex adjVerx; /*the index of the vertex*/ 32 weightType weight; /*the value of the weight*/ 33 ptrToAdjNode next; /*the point to point the next node*/ 34 }; 35 36 /*define the data structure of the adjacent head*/ 37 typedef struct vNode *ptrToVNode; 38 typedef struct vNode { 39 ptrToAdjNode head; /*the point to point the adjacent table node*/ 40 dataType data; /*the space to store the name of the vertex,but some time the vertex has no names*/ 41 } adjList[MAX_VERTEX_NUM]; 42 43 /*define the data structure of graph*/ 44 typedef struct gLNode *ptrTogLNode; 45 typedef struct gLNode { 46 int vertex_number; /*the number of the vertex*/ 47 int edge_nunber; /*the number of the edge*/ 48 adjList g; /*adjacent table*/ 49 }; 50 typedef ptrTogLNode adjacentTableGraph; /*a graph show by adjacent table*/ 51 52 /* 53 create a graph given the vertex number. 54 @param vertexNum The verter number of the graph 55 @return a graph with vertex but no any egdgs 56 */ 57 adjacentTableGraph createLGraph(int vertexNum) { 58 adjacentTableGraph graph; 59 60 vertex v; 61 graph = (adjacentTableGraph) malloc(sizeof(struct gLNode)); 62 graph->vertex_number = vertexNum; 63 graph->edge_nunber = 0; 64 /*initialize the adjacent table*/ 65 for (v = 0; v < graph->vertex_number; v++) { 66 graph->g[v].head = NULL; 67 } 68 return graph; 69 } 70 71 /* 72 insert a edge to graph.We will distinct oriented graph and undirected graph 73 The e->v1 and e->v2 are the vertexs' indexs in the adjacent table 74 @param graph The graph you want to insert edge 75 @param e The edge you want to insert the graph 76 @param isOriented Whether the graph is oriented graph.If the graph is oriented 77 we will set adjacent table graph[v1]->head=v2 and set graph[v1].head=v2 78 otherwise we only set graph[v1].head=v2 79 */ 80 void insertEdgeToLink(adjacentTableGraph graph, edge e, int isOriented) { 81 /*build node<v1,v2>*/ 82 ptrToAdjNode newNode; 83 newNode = (ptrToAdjNode) malloc(sizeof(struct adjNode)); 84 newNode->adjVerx = e->v2; 85 newNode->weight = e->weight; 86 newNode->next = graph->g[e->v1].head; 87 graph->g[e->v1].head = newNode; 88 /*if the graph is directed graph*/ 89 if (!isOriented) { 90 newNode = (ptrToAdjNode) malloc(sizeof(struct adjNode)); 91 newNode->adjVerx = e->v1; 92 newNode->weight = e->weight; 93 newNode->next = graph->g[e->v2].head; 94 graph->g[e->v2].head = newNode; 95 } 96 } 97 98 /* 99 build a graph stored by adjacent table 100 */ 101 adjacentTableGraph buildLGraph(int isOrdered) { 102 adjacentTableGraph graph; 103 edge e; 104 vertex i; 105 int vertex_num; 106 107 scanf("%d", &vertex_num); 108 graph = createLGraph(vertex_num); 109 scanf("%d", &(graph->edge_nunber)); 110 if (graph->edge_nunber) { 111 e = (edge) malloc(sizeof(struct eNode)); 112 for (i = 0; i < graph->edge_nunber; i++) { 113 scanf("%d %d %d", &e->v1, &e->v2, &e->weight); 114 e->v1--; 115 e->v2--; 116 insertEdgeToLink(graph, e, isOrdered); 117 } 118 } 119 120 return graph; 121 } 122 123 /*----------------------define collection and some operator of graph's nodes-----------------------------*/ 124 125 /* 126 * The element of collection 127 */ 128 typedef vertex elementType; 129 130 /* 131 * The index of root element,we use it as the collection name 132 */ 133 typedef vertex setName; 134 135 /* 136 * A array to store the collection,we set the 137 * first index is 0 138 */ 139 typedef elementType setType[MAX_VERTEX_NUM]; 140 141 /* 142 * Initialize collection 143 * @param A <code>elementType</code> array to store the collections,maybe 144 * many collection will be stored in this array 145 * @param n The length of the collection 146 */ 147 void initializeVSet(setType s, int n) { 148 elementType x; 149 for (x = 0; x < n; x++) { 150 s[x] = -1; 151 } 152 } 153 154 /* 155 * Union two collections which is showed by root element.We will union smaller collection 156 * to greater collection and we will update the quantity for greater collection 157 * @param s A <code>elementType</code> array to store the collections,maybe 158 * many collection will be stored in this array 159 * @param root1 The root element of the first collection 160 * @param root2 The root element of the second collection 161 */ 162 void unionCollection(setType s, setName root1, setName root2) { 163 /* 164 * If root2's quantity greater than root1 165 */ 166 if (s[root2] < s[root1]) { 167 s[root2] += s[root1]; 168 s[root1] = root2; 169 } else { 170 s[root1] += s[root2]; 171 s[root2] = root1; 172 } 173 } 174 175 /* 176 * Find the element in which collection and use the root element 177 * to represent this collection and return it.In this method,we will compress path 178 * @param s A <code>elementType</code> array to store the collections,maybe 179 * many collection will be stored in this array 180 * @param x The element we find which collection it in. 181 */ 182 setName find(setType s, elementType x) { 183 if (s[x] < 0) { 184 return x; 185 } else { 186 /* 187 *compress path 188 */ 189 return s[x] = find(s, s[x]); 190 } 191 } 192 193 /* 194 * Check v1 and v1 whether is belong to a same collection. If not union these 195 * two collection,otherwise do nothing. 196 * @param vSet A <code>elementType</code> array to store the collections,maybe 197 * many collection will be stored in this array 198 * @param v1 The index of node in the graph,also the element is the collection. 199 * @param v2 The index of node in the graph,also the element is the collection. 200 * @return If the two element is belong same collection,union them and return 1 201 * else do nothing and return 0; 202 */ 203 int checkCircle(setType vSet, vertex v1, vertex v2) { 204 setName root1 = find(vSet, v1); 205 setName root2 = find(vSet, v2); 206 if (root1 == root2) { 207 return 0; 208 } else { 209 unionCollection(vSet, root1, root2); 210 return 1; 211 } 212 } 213 214 /*-------------define the minimal heap of edge-------------------*/ 215 216 /* 217 * Update the tree whose root element index is p into minimal heap,we use the edgs's 218 * weight as the to construct the minimal heap. 219 * 220 * @param eset A array of edge to store the heap,because the edge is point variable 221 * So the eSet is a edge type array,you can compare it with <code>int* arr</code> 222 * @param The index of the root element. 223 * @param n The length of the heap,the max index is n-1 in this case. And 224 * this heap index is start from zero. 225 */ 226 void percDowm(edge eSet, int p, int n) { 227 int parent, child; 228 struct eNode x; 229 230 x = eSet[p]; 231 for (parent = p; (parent * 2 + 1) < n; parent = child) { 232 /* 233 * Because the first index if from zero,so the left child 234 * is parent*2+1 235 */ 236 child = parent * 2 + 1; 237 /* 238 * Find smaller weigh between the left child and right child 239 */ 240 if ((child != n - 1) && eSet[child].weight > eSet[child + 1].weight) { 241 child++; 242 } 243 if (x.weight <= eSet[child].weight) { 244 break; 245 } else { 246 eSet[parent] = eSet[child]; 247 } 248 } 249 eSet[parent] = x; 250 } 251 252 /* 253 * Initialize eSet heap and update it to be the minimal heap 254 * @param graph A graph which is stored by adjacent list 255 * @param eSet A array of the edge as the minimal heap 256 */ 257 void initializeESet(adjacentTableGraph graph, edge eSet) { 258 vertex v; 259 ptrToAdjNode w; 260 int counter = 0; 261 for (v = 0; v < graph->vertex_number; v++) { 262 for (w = graph->g[v].head; w; w = w->next) { 263 /* 264 * expect for put same edge to it,we only 265 * put <v1,v2> to it. 266 */ 267 if (v < w->adjVerx) { 268 eSet[counter].v1 = v; 269 eSet[counter].v2 = w->adjVerx; 270 eSet[counter].weight = w->weight; 271 counter++; 272 } 273 274 } 275 } 276 /* 277 * Initialize the minimal heap 278 */ 279 for (counter = graph->edge_nunber / 2; counter >= 0; counter--) { 280 percDowm(eSet, counter, graph->edge_nunber); 281 } 282 } 283 284 /* 285 * Get minimal edge from the minimal weight heap 286 * @param eset A array of edge to store the heap,because the edge is point variable 287 * So the eSet is a edge type array,you can compare it with <code>int* arr</code> 288 * @param The current size of the minimal heap 289 * @return The index of the minimal edge in this heap(array) 290 */ 291 int getEdge(edge eSet, int currentSize) { 292 if (currentSize == 0) { 293 return currentSize - 1; 294 } 295 struct eNode temp = eSet[currentSize - 1]; 296 eSet[currentSize - 1] = eSet[0]; 297 eSet[0] = temp; 298 percDowm(eSet, 0, currentSize - 1); 299 return currentSize - 1; 300 } 301 302 /* 303 * Implement the kruskal algorithms to find the minimal created tree 304 * Algorithms thought:we choose the minimal edge from graph but don't 305 * construct a circle each time. Until we choose the V-1 edges. The V 306 * is equal with the quantity of the graph's vertex 307 * In this program,we will use a counter to record the quantity of edges 308 * At last of this method,if we check the quantity of the edge is less than 309 * V-1, it indicates the graph is not collected,so -1 will be return,otherwise we will return 310 * the minimal created tree total weight. 311 * @param graph A graph which is stored by adjacent list 312 * @param mst A A graph which is stored by adjacent list to store the minimal created tree 313 * @return If the graph is collected,the weight of the minimal created tree 314 * will be return, otherwise return -1 315 */ 316 int kruskal(adjacentTableGraph graph, adjacentTableGraph mst) { 317 /* 318 * totalWeight is to record the total weight 319 * of the minimal created tree 320 */ 321 weightType totalWeight; 322 /* 323 * eCounter is to record the quantity of edges which has been 324 * insert the <code>mst<code> 325 * 326 * nextEdge is to record the next minimal edge in the minimal heap 327 */ 328 int eCounter, nextEdge; 329 330 /* 331 *A set of the vertex to store the vertex and implement 332 *some operation such as union find and so on 333 */ 334 setType vSet; 335 336 /* 337 * A array of edge to as the minimal heap to store the egdes 338 */ 339 edge eSet; 340 341 /* 342 * Initialize some variables 343 */ 344 initializeVSet(vSet, graph->vertex_number); 345 eSet = (edge) malloc((sizeof(struct eNode)) * (graph->edge_nunber)); 346 initializeESet(graph, eSet); 347 // mst = createLGraph(graph->vertex_number); 348 totalWeight = 0; 349 eCounter = 0; 350 nextEdge = graph->edge_nunber; 351 while (eCounter < graph->vertex_number - 1) { 352 nextEdge = getEdge(eSet, nextEdge); 353 if (nextEdge < 0) { 354 break; 355 } 356 /* 357 * Check whether a circle between two vertex 358 */ 359 if (checkCircle(vSet, eSet[nextEdge].v1, eSet[nextEdge].v2)) { 360 insertEdgeToLink(mst, eSet + nextEdge, 0); 361 totalWeight += eSet[nextEdge].weight; 362 eCounter++; 363 } 364 } 365 if (eCounter < graph->vertex_number - 1) { 366 totalWeight = -1; 367 } 368 return totalWeight; 369 } 370 371 /*========Use DFS to print the result of the minimal created tree==========*/ 372 /* 373 * A method to access graph 374 */ 375 void visit(adjacentTableGraph graph, vertex v) { 376 printf("%d ", v); 377 } 378 379 /* 380 Depth first search a graph 381 @param graph The graph need to search 382 @param startPoint The fisrt point we start search the graph 383 @paran int *visited The array we use to tag the vertex we has accessed. 384 */ 385 void DFS(adjacentTableGraph graph, vertex startPoint, int *visited) { 386 ptrToAdjNode p; 387 visit(graph, startPoint); 388 p = graph->g[3].head; 389 visited[startPoint] = 1; 390 for (p = graph->g[startPoint].head; p; p = p->next) { 391 if (visited[p->adjVerx] == 0) { 392 DFS(graph, p->adjVerx, visited); 393 } 394 } 395 } 396 397 /* 398 * Initialize a visited array that make them all to zero 399 */ 400 void initVisited(int length, int *visited) { 401 int i; 402 for (i = 0; i < length; i++) { 403 visited[i] = 0; 404 } 405 } 406 407 int main() { 408 adjacentTableGraph graph = buildLGraph(0); 409 adjacentTableGraph mst = createLGraph(graph->vertex_number); 410 vertex visited[graph->vertex_number]; 411 weightType totalWeight = kruskal(graph, mst); 412 printf("%d\n", totalWeight); 413 /*initVisited(graph->vertex_number, visited); 414 DFS(mst, 0, visited);*/ 415 return 0; 416 }