1. 代码
#include<stdio.h>
#include<stdlib.h>
#define MAX_VEX 100
typedef struct
{
int bv, ev, w;
}EDGE;
EDGE edgeset[MAX_VEX];//边集数组;edgnum<=MAX_VEX-1
int creat()
{
int edgnum, i;
printf("输入边数:\n");
scanf("%d", &edgnum);
printf("输入边的起点,终点,权:\n");
for(i=1;i<=edgnum;i++)
{
printf("(bv,ev,w)=");
scanf("%d,%d,%d", &edgeset[i].bv, &edgeset[i].ev, &edgeset[i].w);
}
return edgnum;
}
//排序,使边集数组edgeset[]元素按权值递增顺序排列
void sort(int edgnum)
{
int i, j;
EDGE t;
for(i=1; i<=edgnum-1; i++)
for(j=i+1;j<=edgnum; j++)
{
if(edgeset[i].w>edgeset[j].w)
{
t=edgeset[i];
edgeset[i]=edgeset[j];
edgeset[j]=t;
}
}
}
//寻找顶点属于的连通分量的根节点
int seek(int set[MAX_VEX], int v)
{
int root=v;
while(set[root]>0)
root=set[root];
return root;
}
/*Kruskal算法
1. 各顶点单独为连通分量
2. 按权值将各边排序,选取最小者,要求是起讫点不属于同一连通分量。
使该边的起讫点合并为同一连通分量 。
3. 重复2,直至全部顶点属于同一连通分量
*/
void kruskal(int edgnum)
{
int i;
int v1, v2;
int set[MAX_VEX];
for(i=1;i<MAX_VEX;i++)//i<=vexnum;这里没必要引入 vexnum
set[i]=0;
printf("输出最小生成树\n");
i=0;//待获取的生成树的边在边集数组的下标
while(i++<edgnum)
{
v1=seek(set, edgeset[i].bv);
v2=seek(set, edgeset[i].ev);
if(v1!=v2)
{
printf("(%d,%d) %d\n", edgeset[i].bv, edgeset[i].ev, edgeset[i].w);
set[v2]=v1;//或 set[v2]=v1;
}
}
}
int main()
{
int i, edgnum;
edgnum=creat();
sort(edgnum);
printf("按权值递增顺序输出边\nbv ev w\n");
for(i=1;i<=edgnum;i++)
printf("%d %d %d\n", edgeset[i].bv, edgeset[i].ev, edgeset[i].w);
kruskal(edgnum);
return 0;
}
2. 结果