最小生成树之Kruskal算法C语言

  • 基本思路
    每次都找到不会构成回路的最小边,把这条边的结点收录
  • 举例
如下图:
找到最小边1,把v1,v4收录
找到最小边1,把v6,v7收录
找到最小边2,把v2收录
找到最小边2,把v3收录
找到最小边4,
找到最小边6,把v5收录

最小生成树之Kruskal算法C语言_第1张图片

  • 代码
#include <iostream>
#define MAX 11111
#define SIZE 10
int root[SIZE];//存储各个结点的根结点,用来判断是否有回路 
int check(int i,int j)//检查是否有回路 
{
	int root1,root2;//分别存储i,j结点的根结点 
	while(1)
	{
		if(root[i]<0)
		{
			root1=i;
			break;
		}	
		else{
			i=root[i];
		}
	}
	while(1)
	{
		if(root[j]<0)
		{
			root2=j;
			break;
		}	
		else{
			j=root[j];
		}
	}
	if(root1==root2)//说明有回路 
	{
		return 0;
	}
	else
	{
		if(root[root1]<root[root2])//集合1比集合2大,集合2并入集合1 
		{
			root[root1]+=root[root2];
			root[root2]=root1;
		}
		else//集合2比集合1大,集合1并入集合2 
		{
			root[root2]+=root[root1];
			root[root1]=root2;
		}
		return 1;
	}
}
void Kruskal(int edge[][SIZE],int n)
{
	int count=0;
	int v1,v2;
	int tree[n][n]={0};
	while(count<n)
	{
		int min=MAX;
		v1=v2=-1;
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<n;j++)
			{
				if(edge[i][j]<min)
				{
					min=edge[i][j];
					v1=i;
					v2=j;
				}
			}
		}
		
		if(v1==-1 || v2==-1)
		{
			for(int i=0;i<n;i++)
			{
				for(int j=0;j<n;j++)
				{
					printf("%d ",tree[i][j]);
				}
				printf("\n");
			}
			break;
		}
		edge[v1][v2]=edge[v2][v1]=MAX;	
		if(check(v1,v2))
		{
			count++;
			tree[v1][v2]=tree[v2][v1]=min;
			
			
		}
	}
	
}
int main(int argc, char** argv) {
	int n,m;
	scanf("%d %d",&n,&m);
	int start,end,value;
	int edge[SIZE][SIZE];
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<n;j++)
		{
			
			edge[i][j]=MAX;
		}
		root[i]=-1;
	}
	for(int i=0;i<m;i++)
	{
		scanf("%d %d %d",&start,&end,&value);
		edge[start][end]=edge[end][start]=value;
	}
	Kruskal(edge,n);
	return 0;
}
/*
7 12
0 1 2
0 2 4
2 5 5
5 6 1
6 4 6
4 1 10
3 0 1
3 1 3
3 4 7
3 6 4
3 5 8
3 2 2
*/
  • 运行结果
    最小生成树之Kruskal算法C语言_第2张图片
    结果代表的是新生成的最小生成树的边的情况

你可能感兴趣的:(数据结构与算法)