最小生成树——Krukal算法

1、最小生成数的算法有prim算法和krukal算法。

prim算法实现最小生成树见这个链接

最小生成树的学习视频

2、这次说Krukal算法实现最小生成树

在这里插入图片描述

提醒:本代码第一个元素的下表从1开始,而不是从0开始,注意就好。

最后有 测试数据

//最小生成树——Krukal算法 
#include<iostream>
#include<algorithm>
#include<malloc.h>
#define Max 10001    //模拟无穷大 
#define MaxSize 10   //最多点数 
using namespace std;

typedef struct{
	int left;
	int right;
	int weight;	
}edgeArray;

//1)图的数据类型 
typedef struct 
{
	int vertex[MaxSize];//存储点的信息 	
	int belong[MaxSize];//属于分支号 
	int edge[MaxSize][MaxSize];//边的信息 
	int vertexNum;//点的个数
	int edgeNum;// 边的个数 
}MGraph;

//2)构造一个图 
MGraph  CreatGraph(int n,int m,edgeArray ea[]){
	MGraph G;
	int a,b,c;
	//点 边 
	G.vertexNum=n;
	G.edgeNum=m;
	//点的信息
	for(int i=1;i<=G.vertexNum;i++){
		G.vertex[i]=i;
		G.belong[i]=i;  //一开始,要把每个点看成独立的,即属于的分支是他自己 
	} 
	//边邻接关系的初始化
	for(int i=1;i<=G.vertexNum;i++){
		for(int j=1;j<=G.vertexNum;j++){
			if(i==j){
				G.edge[i][j]=0;
			}else{
				G.edge[i][j]=Max;
			}	
		}
	}
	//输入m行边的信息 
	printf("请输入 点号 点号 边值:\n"); 
	for(int i=1;i<=G.edgeNum;i++){
		scanf("%d %d %d",&a,&b,&c);
		G.edge[a][b]=c;
		G.edge[b][a]=c;//无向图 
		ea[i].left=a;
		ea[i].right=b;
		ea[i].weight=c;
	} 
	return G;
}

//3)对EDGE升序排序  sort函数的排序方式函数,<algorithm>+sort(array,cmp) 
bool cmp(edgeArray e1,edgeArray e2){
	return e1.weight<e2.weight;
}

//4)核心算法
MGraph Krukal(MGraph G,int n,int m,edgeArray ea[]){ 
	//边邻接关系的 复初始化
	for(int i=1;i<=G.vertexNum;i++){
		for(int j=1;j<=G.vertexNum;j++){
			if(i==j){
				G.edge[i][j]=0;
			}else{
				G.edge[i][j]=Max;
			}	
		}
	}
	
	//连接新边	
	edgeArray e;
	int isTongYi=0;	//是否所有点的分支号统一? 
	int edgeNumTrue = 0; 
	for(int i=1;i<=m;i++){
		e = ea[i];
		if(G.belong[e.left]!=G.belong[e.right]){//一边的两点属于不同分支 
			int l = G.belong[e.left];
			int r = G.belong[e.right]; 
			for(int j=1;j<=n;j++){//默认把右分支全部统一成左分支 
				if(G.belong[j]==r){
					G.belong[j] = l;	
				}
			} 
		}
		
		//全局是否同一图
		isTongYi = 1;
		for(int j=2;j<=n;j++){
			if(G.belong[j]!=G.belong[j-1]){
				isTongYi =0;
				break;
			}
		} 
		if(isTongYi == 1){
			edgeNumTrue = i;
			break;
		}
	}
	G.edgeNum = edgeNumTrue;
	for(int i = 1;i<=G.edgeNum;i++){
		G.edge[ea[i].left][ea[i].right] = ea[i].weight;
		G.edge[ea[i].right][ea[i].left] = ea[i].weight;
	} 
	return G;
}

void display(MGraph G){
	for(int i =1;i <= G.vertexNum;i++){
		for(int j =1;j <= G.vertexNum;j++){
			if(G.edge[i][j]==Max)	cout<<"max ";
			else cout<<G.edge[i][j]<<" ";
		}	
		cout<<endl;
	}
}

int main(){
	int n;
	int m;
	printf("请输入点数和边数:\n"); 
 	scanf("%d %d",&n,&m);
	edgeArray ea[MaxSize*MaxSize];
	MGraph G;
	G = CreatGraph(n,m,ea);
	cout<<endl<<"原始图";
	display(G); 
	sort(ea+1,ea+m+1,cmp);
	 
	G = Krukal(G,n,m,ea);
	cout<<endl<<"最小生成树图";
	display(G); 
	
	return 0;
}

3、测试数据 根据这个图,找最小生成树

在这里插入图片描述

4、改进

完全可以不初始化之前的图,一边输入 (点号 点号 边值),一边记录到edgeArray里面,然后排序,然后进行Krukal算法。你可以试试。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值