最小生成树之克鲁斯卡尔算法(C语言实现)

Kruskal算法关键:
如何判断新选取的一条边加入到已选取的边集合中是否出现回路?可以通过判断该边的两个端点是否属于同一连通分量的方法来解决。

Kruskal算法步骤:
(1)对每一个边进行初始化,并为该边的顶点构建一个集合,同时记录下该边的权重;
(2)根据边的权重进行排序;
(3)按边权重由小到大,依次取一条边,若该边的两个端点没有在一个集合,则可以将该边加入已选取的边集合中去;若在,则忽略该边。不断重复选下一条边,直到边数等于顶点数-1。

实例以及代码
最小生成树之克鲁斯卡尔算法(C语言实现)_第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;
}

运行结果:
最小生成树之克鲁斯卡尔算法(C语言实现)_第2张图片

你可能感兴趣的:(数据结构经典基础算法实现)