Kruskal算法关键:
如何判断新选取的一条边加入到已选取的边集合中是否出现回路?可以通过判断该边的两个端点是否属于同一连通分量的方法来解决。
Kruskal算法步骤:
(1)对每一个边进行初始化,并为该边的顶点构建一个集合,同时记录下该边的权重;
(2)根据边的权重进行排序;
(3)按边权重由小到大,依次取一条边,若该边的两个端点没有在一个集合,则可以将该边加入已选取的边集合中去;若在,则忽略该边。不断重复选下一条边,直到边数等于顶点数-1。
实例以及代码
//定义边的数据结构,声明相应的变量
typedef struct{
int s;
int e;
int weight;
}Bian;
int A[4][4]={{0,4,3,1}, //邻接矩阵存储图
{4,0,5,0},
{3,5,0,2},
{1,0,2,0}};
Bian g[20];
int k=0;
int mark[4]={0,1,2,3}; //顶点的集合编号
//将邻接矩阵的数据转移到结构体中
void Initialize(){
int i,j;
for(i=0;i<4;i++)
for(j=i+1;j<4;j++)
{
if(A[i][j]!=0)
{
g[k].s=i;
g[k].e=j;
g[k++].weight=A[i][j];
}
}
}
//按照边权值大小进行排序
void Sort(){
int i,j;
Bian t;
for(j=0;j<k;j++)
for(i=0;i<k-j-1;i++)
{
if(g[i].weight>g[i+1].weight)
{
t=g[i];
g[i]=g[i+1];
g[i+1]=t;
}
}
}
将两个端点所在的集合进行合并
void Merge(int a,int b){
int t,i;
t=mark[a];
for(i=0;i<4;i++)
if(mark[i]==t)
mark[i]=mark[b];
}
//依次取边
void AddBian(){
int i,number=0;
Bian t;
for(i=0;i<k;i++)
{
t=g[i];
if(mark[t.e]!=mark[t.s]) //满足则记录该边
{
number++;
Merge(t.e,t.s);
printf("%d ",t.weight);
}
if(number==3) //当边为顶点数-1时则停止
{
printf("\nTrue");
return;
}
}
}
//主函数,负责调用以上函数
int main(){
Initialize();
Sort();
AddBian();
return 0;
}
运行结果: