数据结构-最小生成树

最小生成树

  • 说明:本人还是初学者,以下给出的代码是教材数据结构C语言版第二版(严蔚敏 李冬梅 吴伟民 编著)中关于最小生成树Kruskal算法代码段的整合,本人用于简单的城市间道路网课程设计,仅供参考
  • 完整代码:
#include <iostream>
using namespace std;

#include <fstream>

#define MaxInt 32767                                                    //表示极大值,即 ∞
#define MVNum 100                                                       //最大顶点数
#define OK 1

typedef char VerTexType;                                               //假设顶点的数据类型为字符型 
typedef int ArcType;                                                   //假设边的权值类型为整形 

ifstream infile;                                                       //定义输入文件流对象 

typedef struct
{//图的邻接矩阵存储表示 
	VerTexType vexs[MVNum];                                            //顶点表 
	ArcType arcs[MVNum][MVNum];                                        //邻接矩阵 
	int vexnum, arcnum;                                                //图的当前点数和边数 
}AMGraph;
AMGraph G;

typedef struct Edge
{ 
	VerTexType Head;                                                   //边的始点
	VerTexType Tail;                                                   //边的终点
	ArcType lowcost;                                                   //边上的权值
};
Edge Edges[MVNum];                                                     //辅助数组Edges和E的定义 
Edge E;

int Vexset[MVNum];                                                     //辅助数组Vexset存放 

int LocateVex(AMGraph G, char u)
{//返回顶点u在图G中的位置
	int   i;
	for (i = 0; i<G.vexnum; ++i)                                       //输入的顶点u与顶点表中的顶点依次比较 
		if (u-G.vexs[i]=='\0')
			return   i;
	return   OK;
}

int CreateUDN(AMGraph &G)
{//采用邻接矩阵表示法,创建无向图G 
	infile>> G.vexnum >> G.arcnum;                                    //输入总顶点数,总边数
	for (int i = 0; i<G.vexnum; i++) {                                //依次输入点的信息 
		infile>> G.vexs[i];
	}
	for (int i = 0; i<G.vexnum; i++) {                                //初始化邻接矩阵,边的权值均置为极大值MaxInt
		for (int j = 0; j<G.vexnum; ++j) {
			G.arcs[i][j] = MaxInt;
		}
	}
	for (int k = 0; k<G.arcnum; ++k) {
		char v1, v2;
		int i, j, w;
		infile >> v1 >> v2 >> w;                                      //输入一条边依附的顶点和权值
		i = LocateVex(G, v1); j = LocateVex(G, v2);                   //确定v1和v2在G中的位置,即顶点数组的下标
		G.arcs[i][j] = w;                                             //边<v1,v2>的权值置为w
		G.arcs[j][i] = G.arcs[i][j];                                  //置<v1,v2>的对称边<v2,v1>的权值为w	 
	}
	return OK;
}

int Sort(Edge Edges[])
{//将数组Edge中的元素按权值从小到大排序
	int i,j,k=0;
	for (i = 0; i<G.vexnum; i++) {                                    //边集数组初始化,只考虑上三角矩阵  
		for (j = i; j<G.vexnum; j++) {
			if (G.arcs[i][j]!=MaxInt) {
				Edges[k].Head = G.vexs[i];
				Edges[k].Tail = G.vexs[j];
				Edges[k].lowcost = G.arcs[i][j];
				k++;				
			}
		}
	}
	for (i = 0; i<G.arcnum-1; i++) {                                  //对边集数组进行选择排序  
		for (j = i + 1; j<G.arcnum; j++) {
			if (Edges[i].lowcost > Edges[j].lowcost) {
				E = Edges[i];
				Edges[i] = Edges[j];
				Edges[j] = E;
			}
		} 
	}
}

void MiniSpanTree_Kruskal(AMGraph G)
{//无向网G以邻接矩阵形式存储,构造G的最小生成树T,输出T的各条边
	int v1, v2, vs1, vs2;
	int min=0;
	Sort(Edges);                                                      //将数组Edge中的元素按权值从小到大排序
	for (int i = 0; i<G.vexnum; i++)                                  //辅助数组,表示各顶点自成一个连通分量
		Vexset[i] = i;
	cout<<"最小生成树中包括的城市间的道路有:"<<endl;
	for (int i = 0; i<G.arcnum; i++) {                                //依次查看数组Edge中的边
	
		v1 = LocateVex(G, Edges[i].Head);                             //v1为边的始点Head的下标
		v2 = LocateVex(G, Edges[i].Tail);                             //v2为边的终点Tail的下标
		vs1 = Vexset[v1];                                             //获取Edge[i]的始点所在的连通分量vs1
		vs2 = Vexset[v2];                                             //获取Edge[i]的终点所在的连通分量vs2
		if (vs1 != vs2) {                                             //边的两个顶点分属不同的连通分量
			cout <<"边:"<<Edges[i].Head <<"--"<< Edges[i].Tail
			<<",权值:"<<Edges[i].lowcost<<endl;                       //输出此边和权值 
			min=min+Edges[i].lowcost;                                 //累加计算最小生成树的代价
			for (int j = 0; j<G.vexnum; j++)                          //合并vs1和vs2两个分量,即两个集合统一编号
				if (Vexset[j] == vs2)  Vexset[j] = vs1;               //集合编号为vs2的都改为vs1 
		}
	}
	cout<<"最小生成树的代价为:"<<min<<endl;
}

int sc()
{
cout<<"输出城市间距离网的邻接矩阵:"<<endl;
	for (int i = 0; i<G.vexnum; i++) {
		for (int j = 0; j<G.vexnum; j++) {
			if (G.arcs[i][j] == MaxInt)                               //将MaxInt的数值替换为字符 ∞
				cout<<"∞"<<" ";
			else
				cout<<G.arcs[i][j]<<"  ";
		}
		cout<<endl;
	}
	return OK;
}

int main()
{
	infile.open("1.txt",ios::in);
	if(!infile) {
		cerr<<"文件打开失败!"<<endl;
		exit(1); 
	}
	CreateUDN(G);
	sc();
	MiniSpanTree_Kruskal(G);
}

文件格式示例:
1.txt
结果如下:
在这里插入图片描述

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值