克鲁斯卡尔算法构造最小生成树——C++

本文介绍了一种使用邻接矩阵存储结构,通过克鲁斯卡尔算法构造无向图最小生成树的方法。首先,定义了图的邻接矩阵结构,然后通过输入顶点数和边数,以及边的两端顶点和权值,创建无向图。接着,使用邻接矩阵初始化边的结构,并按权值排序。最后,通过克鲁斯卡尔算法找到并连接不在同一连通分量中的最小边,输出这些边,从而得到最小生成树。
摘要由CSDN通过智能技术生成

利用邻接矩阵做存储结构——通过克鲁斯卡尔算法构造最小生成树,话不多说,且看代码如下:


#include<iostream>
using namespace std;
//二维数组存储邻接矩阵
//一维数组存储顶点信息
//-----图的邻接矩阵表示----
#define MaxInt 32767	//表示极大值
#define MVNum 100		//最大顶点数
typedef string VerTexType;//假设顶点的数据类型为字符串型
typedef int ArcType;	//假设边的权值类型为字符串型
typedef struct
{
	VerTexType vexs[MVNum];//顶点表
	ArcType arcs[MVNum][MVNum];//邻接矩阵各边之间的权值 
	int vexnum, arcnum;//图的当前顶点数和边数
}AMGraph;
//采用邻接矩阵表示法创建无向网
//返回顶点在邻接矩阵中对应的下标
int LocateVex(AMGraph& G, char *v1)
{
	for (int i = 0; i<G.vexnum; i++)
	{
		if (v1 == G.vexs[i])
			return i;
	}
}
void CreateUDN(AMGraph& G)
{
	int i, j, k,w;
	string v1,v2;
	cin >> G.vexnum >> G.arcnum;		//输入总顶点数和总边数
	for (i = 0; i < G.vexnum; ++i)
		cin >> G.vexs[i];		//依次输入点的信息***顶点数组
	for (i = 0; i < G.vexnum; ++i)
		for (j = 0; j < G.vexnum; ++j)
			G.arcs[i][j] = MaxInt;		//初始化邻接矩阵,使每个权值初始化为极大值
	for (k = 0; k < G.arcnum; ++k)		//构造邻接矩阵
	{
		cin >> v1 >> v2 >> w;			//输入一条边依附的顶点及其权值
		i = LocateVex(G, &v1[0]);			//确定v1和v2在G中的位置,即顶点数组的下标
		j = LocateVex(G, &v2[0]);
		G.arcs[i][j] = w;				//边<v1,v2>的权值置为w
		G.arcs[j][i] = G.arcs[i][j];	//置<v1,v2>的对称边<v2,v1>权值为w
	}
	for (int i = 0; i < G.vexnum; i++)
	{	
		for (int j = 0; j < G.vexnum; j++)
				cout << G.arcs[i][j] << "\t";
	cout << endl<<endl;
	}
}
//————存储边———— 
struct Edge
{
	VerTexType Head;
	VerTexType Tail;
	ArcType lowcost;
}Edge[MVNum];
//存边数组的初始化——将边的首尾顶点,权,都存到数组里面 
void init(AMGraph G,struct Edge *edge)
{
	int k=0;
	for(int i=0;i<G.vexnum;i++)
		for(int j=i;j<G.vexnum;j++)
		{
			while(G.arcs[i][j]!=MaxInt)
			{
				edge[k].Head=G.vexs[i];
				edge[k].Tail=G.vexs[j];
				edge[k].lowcost=G.arcs[i][j];
				k++;
				break;
				}	
			
		}
}
void swap(struct Edge *a,struct Edge *b)
 {
 	struct Edge tem;
 	
 	tem.Head=a->Head;
 	a->Head=b->Head;
 	b->Head=tem.Head;
 	
 	tem.Tail=a->Tail;
 	a->Tail=b->Tail;
 	b->Tail=tem.Tail;
 	
 	tem.lowcost=a->lowcost;
 	a->lowcost=b->lowcost;
 	b->lowcost=tem.lowcost;
 }
//按照权值从小到大排序,注意:顶点要随着权而变化 
void Sort(struct Edge *edge,int n)
{
	int begin=0,end=n-1;
	while(begin<end)
	{
		int max=begin;
		int min=begin;
		//找出最值的下标 
		for(int i=begin;i<=end;++i)
		{
			if(edge[i].lowcost>edge[max].lowcost)
				max=i;
			if(edge[i].lowcost<edge[min].lowcost)
				min=i;
		}
		//最小值放到开头,和开头交换 
		swap(&edge[min],&edge[begin]);//权值与下标的关系会变化 
		if(begin==max)
			max=min;
		//最大值放到末尾 
		swap(&edge[max],&edge[end]);//会 
		++begin;
		--end;
	}
 } 
//标识各个顶点所属的连通分量 
int Vexset[MVNum];
//——克鲁斯卡尔算法—— 

void Kruskal(AMGraph G)
{

	init(G,Edge);
	int i,j,v1,v2, vs1,vs2;
	Sort(Edge,G.arcnum);//对各条边按照权值大小进行排序 
	for(i=0;i<G.vexnum;++i)
		Vexset[i]=i;//各点连通分量初始化,先初始化为自身的下标 
		
	for(i=0;i<G.arcnum;++i)
	{
		
		v1=LocateVex(G,&Edge[i].Head[0]);//起始点的下标 
		v2=LocateVex(G,&Edge[i].Tail[0]);//终点的下标 
		vs1=Vexset[v1];//连通分量 
		vs2=Vexset[v2];
		if(vs1!=vs2)
		{
			cout<<Edge[i].Head<<Edge[i].Tail<<endl;
			//Vexset[v2]=vs1; //这个想法只适用于连通分量=vs2的点只有一个 
			for(j=0;j<G.vexnum;++j)
				if(Vexset[j]==vs2)
					Vexset[j]=vs1;
		}
	}
	
}
int main()
{
	AMGraph G;
	CreateUDN(G);
	cout<<"最短路径:"<<endl;
	Kruskal(G); 
 } 


输入实例:

6 10
v1 v2 v3 v4 v5 v6    
v1 v2 6
v1 v3 1
v1 v4 5
v2 v3 5
v2 v5 3
v3 v5 6
v3 v4 5
v3 v6 4
v4 v6 2
v5 v6 6 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

try again!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值