Kruskal算法是在处理一个森林——树的集合。开始时将图的每个顶点看做一棵树(集合),然后采用贪婪策略,每次从所有边中依次选出(Find)权值最小的边,当改边的两个端点不在同一集合时,则将终点所在集合与起点集合合并(Union),直到依次处理完所有的边,算法终止,此时所有的顶点在一个树中,即为最小生成树。
其基本步骤如下图所示:
图一:初始时刻,所有顶点在各自集合中 图二:选择最小权值边AD,将集合A与集合D合并
图三:选择边CE,将集合C与集合E合并 图四:选择边BE,将集合ABDF与集合EC合并
图五:选择边EG,将集合G与集合ABCDEF合并。完成,所有点在同一集合中
实现代码:
<span style="color:#333333;">#include <stdio.h> #include <stdlib.h> #define INF 0x7fffffff struct Graph { int v;//顶点数 int e;//边数 int graph[][MAX];//边权重数组 }; struct Edge { int s;//边起点 int m;//边终点 int w;//边权值 }; //将边按权值从小到大进行堆排序 void HeapSort(struct Edge* E); int Kruskal(Graph G,int n) { int i,j,sum=0; int* vset=(int*)malloc(n*sizeof(int));//标识每个顶点所属的集合 struct Edge* E=(struct Edge*)malloc((n-1)*sizeof(Edge));//边数组 for(i=0;i<n;++i) vset[i]=i; for(i=0;i<n-1;++i) for(j=0;j<n-1;++j) { E[i].s=i; E[i].m=j; E[i].w=G.graph[i][j]; } HeapSort(E);//排序 int sv;//记录起点所属集合 int mv;//记录终点所属集合 for(i=0;i<n-1;++i)//每次按权值大小,取出一条未处理的边 { sv=vset[E[i].s]; mv=vset[E[i].m]; //边两端点不在同一集合,且两点确实连通 if(sv!=mv && G.graph[E[i].s][E[i].m]<INF) { printf("%d to %d : %d /n",E[i].s,E[i].m,E[i].w); sum+=G.graph[E[i].s][E[i]].w; for(j=0;j<n-1;++n)//集合合并:将终点及其集合中的所有其他顶点移到起点所在集合 { if(vset[j]==mv) vset[j]=sv; } } } free(vset); free(E); return sum; }</span>
原文:http://blog.csdn.net/yuyixinye/article/details/44618213