数据结构实验——用邻接矩阵存储,并按Prim算法求最小生成树实验

用邻接矩阵存储,并按Prim算法求最小生成树 实验

2.1 实验内容

根据书P262习题3给定的无向带权图,用邻接矩阵作为存储结构,用prim算法构造其最小生成树。

对图G(V,E)设置集合S,存放已访问的顶点,然后每次从集合V-S中选择与集合S的最短距离最小的一个顶点(记为u),访问并加入集合S。之后,令顶点u为中介点,优化所有从u能到达的顶点v与集合S之间的最短距离。执行n次(n为顶点个数),直到集合S已包含所有顶点。

2.2文件结构、开发环境等说明

开发环境版本

VisualStudio 2022

工程文件名

ex2_2_prim.sln

头文件个数

3个

源程序文件个数

1个

文件名

文件类型

功能简介

备注

AdjMatrixUndirNetwork.h

头文件

无向图的邻接矩阵类类模板头文件,包括数据成员及成员函数的声明与定义

Prim.h

头文件

Prim算法实现最小生成树的构造

Assistance.h

头文件

辅助软件包

TestPrim.cpp

源文件

测试文件

2.3实现技术

1、邻接矩阵作为存储结构

在AdjMatrixUndirNetwork.h头文件中,用邻接矩阵类作为图的存储结构,该头文件中包含了邻接矩阵类的数据成员及成员函数的声明与定义(这里不做代码展示)。

2、辅助数组closearc[]

在利用普里姆算法构造最小生成树过程中,需要设置一个辅助数组closearc[ ],以记录从V-U中顶点到U中顶点具有最小权值的边。对每一个顶点v属于V-U,在辅助数组中有一个分量closearc[v],它包括两个域:lowweight和nearvertex。其中,lowwcight中存放顶点v到U中的各顶点的边上的当前最小权值(lowweight=0表示v属于U);nearvertex记录顶点v到U中具有最小权值的那条边的另一个邻接顶点u(nearvertex=-1表示该顶点v为开始顶点)。

template <class ElemType, class WeightType>
struct CloseArcType {
	WeightType lowweight;
	int nearvertex;
};

3、Prim算法

在普里姆算法中,主要有两个并列的for循环。设连通网络由n个顶点和e条边组成,则第一个for循环执行n-1次对辅助数组closear[]进行初始化;第二个for循环是个二重嵌套循环,外循环执行n-1次把n-1个顶点加入U中,对每加入一个顶点到U,有两个并列的for循环分别实现查找具有最小权值的边和修改辅助数组closearc[]。

在下面的普里姆算法描述中,连通网络采用邻接矩阵作为存储结构,并假设普里姆算法从顶点A(设项点A的序号为0)出发(即u=0)。普里姆算法步骤如下。

1)初始化辅助数组closearc[]。

2)重复下列步骤3)和4) n-1次。

3)在closearc[]中选择lowweight≠0&&lowweight最小的顶点v,即选中的权值最小的边为(closearc[v].nearvertex,i)。将closearc[v].lowweight改为0,表示顶点i已加入顶点集U中,并将边(closearc[v].ncarvertex,v)加入生成树T的边集合。

template <class ElemType, class WeightType>
void MiniSpanTreePrim(const AdjMatrixUndirNetwork<ElemType, WeightType>& g, int u0)// 初始条件:存在网g,u0为g的一个顶点
{// 操作结果:用Prim算法从u0出发构造网g的最小代价生成树
	WeightType min;
	ElemType v1, v2;
	int vexnum = g.GetVexNum();
	CloseArcType<ElemType, WeightType>* closearc;
	if (u0 < 0 || u0 >= vexnum)
		throw Error("顶点u0不存在!"); // 抛出异常
	int u, v, k;						// 表示顶点的临时变量 
	closearc = new CloseArcType<ElemType, WeightType>[vexnum];	// 分配存储空间
	for (v = 0; v < vexnum; v++) {	// 初始化辅助数组adjVex,并对顶点作标志,此时U = {v0}
		closearc[v].nearvertex = u0;
		closearc[v].lowweight = g.GetWeight(u0, v);
	}
	closearc[u0].nearvertex = -1;
	closearc[u0].lowweight = 0;
	for (k = 1; k < vexnum; k++) {	// 选择生成树的其余g.GetVexNum() - 1个顶点
		min = g.GetInfinity();
		v = u0;// 选择使得边<w, adjVex[w]>为连接V-U到U的具有最小权值的边
		for (u = 0; u < vexnum; u++)
			if (closearc[u].lowweight != 0 && closearc[u].lowweight < min) {
				v = u;
				min = closearc[u].lowweight;
			}
		if (v != u0) {
			g.GetElem(closearc[v].nearvertex, v1);
			g.GetElem(v, v2);
			cout << "边:( " << v1 << ", " << v2 << " ) 权:" << min << endl; // 输出边及权值
			closearc[v].lowweight = 0;		// 将w并入U
			for (u = g.FirstAdjVex(v); u != -1; u = g.NextAdjVex(v, u)) 	// 新顶点并入U后重新选择最小边
				if (closearc[u].lowweight != 0 && (g.GetWeight(v, u) < closearc[u].lowweight)) {	// <v, w>为新的最小边
					closearc[u].lowweight = g.GetWeight(v, u);
					closearc[u].nearvertex = v;
				}}}
	delete[]closearc;	}		// 释放存储空间  

4、测试代码

调用MiniSpanTreePrim(net, u0)函数,生成最小生成树(只展示重要部分)

cout << "从顶点A开始,利用Prim算法产生最小生成树的边:" << endl;
int u0 = 0;
MiniSpanTreePrim(net, u0);		// Prim算法
cout << endl;

2.4测试结果

1、测试实例

 2、用存储结构表示

3、Prim算法

 

完整代码可看资源区

创作不易~麻烦点个赞~~谢谢大家~~~ 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值