数据结构实验——破圈法求最小生成树

破圈法求最小生成树 实验

4.1 实验内容

根据书P262习题10给定的无向带权图,用破圈法构造其最小生成树。

所谓“破圈法”就是“任取一圈,去掉圈上权最大的边”,反复执行这一步骤,直到没有圈为止。请给出用“破圈法”求解给定的带权连通无向图的一最小生成树的详细算法,并用程序实现所给出的算法(注:圈就是回路)。

4.2开发环境等说明

开发环境版本

VisualStudio 2022

工程文件名

ex2_2_prim.sln

头文件个数

5个

源程序文件个数

1个

文件名

文件类型

功能简介

备注

AdjMatrixUndirNetwork.h

头文件

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

Edge.h

头文件

边结点类模板头文件,包括数据成员及成员函数的声明与定义

Assistance.h

头文件

辅助软件包

MaxHeap.h

头文件

最大堆类模板头文件,包括数据成员及成员函数的声明与定义

MiniSpanTreeTearCycle.h

头文件

破圈法构造最小生成树

text.cpp

源文件

测试文件

4.3实现技术

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

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

2、最大堆存放边

在破圈法中,以边的权值为关键字构造一个最大堆(这里不做堆类的代码展示)

3、边结点类模板

在这个边类中定义了一条边依附的两个顶点vertexl、vertex2以及边的权weight。另外,除了构造函数外,重载了赋值运算、>=、<=、>、<四个关系运算。

template <class ElemType, class WeightType>
class Edge
{
public:
	ElemType vertex1, vertex2;
	WeightType weight;
	Edge(ElemType v1, ElemType v2, WeightType w);
	Edge() { vertex1 = 0; vertex2 = 0; weight = 0; };
	Edge<ElemType, WeightType>& operator=(const Edge<ElemType, WeightType>& Ed);
	bool operator >=(const Edge<ElemType, WeightType>& Ed);
	bool operator <=(const Edge<ElemType, WeightType>& Ed);
	bool operator >(const Edge<ElemType, WeightType>& Ed);
	bool operator <(const Edge<ElemType, WeightType>& Ed);
};

4、判断无向网是否连通

在邻接矩阵类中声明并定义了函数IsConnect(),利用DFS遍历该无向图,遍历到的顶点就将其状态设为VISITED,后再用for循环遍历所有顶点,如果都为VISITED则该图连通,反之。

template <class ElemType, class WeightType>
bool AdjMatrixUndirNetwork<ElemType, WeightType>::IsConnect() 
{
	int p1 = 1;
	DFSTraverse(Write<ElemType>);
	for (int v = 0; v < this->GetVexNum(); v++)
		if (this->GetTag(v) == UNVISITED)
			p1 = 0;
	return p1;
}

5、破圈法

连通图的生成树包括图中的全部n个顶点和足以使图连通的n-1条边,最小生成树是边上权值之和最小的生成树。故可按权值从大到小对边进行排序,然后从大到小将边

删除。每删除一条当前权值最大的边后,就测试图是否仍连通,若不再连通,则将该边恢复。不断重复上述过程,选取边进行删除,直到图中剩下n-1条边为止。

template <class ElemType,class WeightType>
void MiniSpanTreeTearCycle(AdjMatrixUndirNetwork<ElemType, WeightType>& g)
{
	int count, VexNum = g.GetVexNum(), EdgeNum = g.GetEdgeNum();
	Edge<ElemType, WeightType>edge;
	MaxHeap< Edge<ElemType, WeightType>>ha(g.GetEdgeNum());//以边的权值为关键字建立一个最大堆
	ElemType v1, v2;
	int u, v;
	for(v=0;v<g.GetVexNum();v++)
		for(u=g.FirstAdjVex(v);u>=0;u=g.NextAdjVex(v,u))
			if (v < u)
			{
				g.GetElem(v, v1);
				g.GetElem(u, v2);
				edge.vertex1 = v1;
				edge.vertex2 = v2;
				edge.weight = g.GetWeight(v, u);
				ha.Insert(edge);
			}
	count = 0;
	while ((EdgeNum - count) > VexNum - 1) {
		ha.DeleteTop(edge);
		v1 = edge.vertex1;
		v2 = edge.vertex2;
		v = g.GetOrder(v1);
		u = g.GetOrder(v2);
		g.DeleteArc(v, u);
		if (g.IsConnect()) {
			count++;
			cout << "删除的第" << count << "边:(" << v1 << ", " << v2 << " )权:" << edge.weight << endl;
		}
		else
			g.InsertArc(v, u, edge.weight);
	}
}

4.4测试结果

1、测试实例

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

3、破圈法得到最小生成树

 

完整代码可看资源区

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值