数据结构_图的最小生成树(prim和kruskal算法)

本文详细介绍了如何构建图的最小生成树,分别讲解了Prim算法和Kruskal算法的思想、代码实现,并通过实例进行了演示。这两种算法在数据结构中常用于寻找连通网的最小代价生成树。
摘要由CSDN通过智能技术生成

对于现实生活中对于多地搭建最小代价的通信网络,n个城市之间需要搭建n-1条通信线路,其重在于n个城市之间最多的n✖(n-1)/2条线路的合理选择出n-1条。使用连通网表示,顶点表示城市,边权值表示通信代价。那么对于连通网可以建立不同的生成树,对于其权值之和最小的生成树,也是就是连通网的最小生成树,简称最小生成树。

本文前沿知识——图的存储结构_邻接矩阵表示。可查看本专栏内容—— 数据结构_图.

MST性质

构建最小生成树的算法,其中多数算法利用了最小生成树的简称MST的性质

MST
假设N=(V,E)是一个连通网,U是顶点集V的一个非空子集。若(u,v)是一条具有最小权值的边,其中u∈U,v∈ V-U,则必存在一棵包含(u,v)的最小生成树。
反证法证明

  1. 文字叙述:假设网N的任何一棵最小生成树都不包含(u, v)。设T是连通网上的一棵最小生成树,当将边(u, v)加入到T中时,由生成树的定义,T中必存在一条包含(u, v)的回路。另一方面,由于T是生成树,则在T上必存在另一条边(u′, v′),其中u′∈U,v′∈V−U,且u和u′之间、v和v′之间均有路径相通。删去边(u′, v′),便可消除上述回路,同时得到另一棵生成树T′。因为(u, v)的权值不高于(u′, v′),则T′的权值亦不高于T,T′是包含(u, v)的一棵最小生成树。由此和假设矛盾。
  2. 图表述:
    在这里插入图片描述

prim算法

算法思想

构造过程不断加点,别称“加点法”

  1. 构造步骤:
    假设N=(V, E)是连通网,TE是N上最小生成树中边的集合。
    (1) U={ u0 }(u0∈V),TE={ }。
    (2) 在所有u∈U,v∈V−U的边(u, v)∈E中找一条权值最小的边(u0, v0)并入集合TE,同时v0并入U。
    (3)重复(2),直至U=V为止。
  2. 书上实例
    在这里插入图片描述

代码实现

核心代码:


/// ===============================================
/// prim算法实现
/// ===============================================


struct E {
   
	VertexType v;
	Edgetype e;
}EDG[MAX];            
//n个顶点,选择其中一个作为边起始,最多有n-1条边
//存储边信息,v存储的是(u,v)边,e存储边(u,v)的权值。
//从所有n∈U中选择最小边的操作就是,加入一个顶点进U时,先<u,i>(0<i<n)将数组的权值比它大的更新


//返回数组EDG中的最小边
int minE(E e[MAX],int n) {
   
	int j = 0;
	int min = -1;
	for (int i = 0; i < n; ++i) {
   
		if (j == 0) {
   
			if (e[i].e != 0) {
   
				min = i;
				++j;
			}
		}
		else {
   
			if (e[i].e != 0) {
   
				if (e[i].e < e[min].e)
					min = i;
			}
		}
	}
	return min;
}

void prim(G_Amatreix g,VertexType v) {
   
	int k = LocateV(g, v);
	for (int i = 0; i < g.n; ++i) {
               //用顶点存在的边<u0,i>将EDG初始化
		if (i != k)
			EDG[i] = {
   v,g.E[k][i]};
		else   
			EDG[i].e = 0;                      //e置为0,表示该加入U
	}

	for (int i = 1; i < g.n; ++i) {
                //选择最小权值边并输出
		k = minE(EDG,g.n);
		printf("%c——%c\n", EDG[k].v, g.V[k]);
		EDG[k].e = 0;                           //e置为0,表示该加入U


		//用最小权值边的边终点存在的边<k,i>将EDG(若边权值比之前的小,则替换)
		for (int j = 0; j < g.n; ++j) {
   
			if (g.E[k][j] < EDG[j].e)
				EDG[j] = {
    g.V[k],g.E[k][j] };
		}
	}
}

测试结果:
在这里插入图片描述

kruskal算法

算法思想

构造过程不断加最小边,别称“加边法”

  1. 构造步骤:
    假设N=(V, E)是连通网,将N中的边从小到大顺序排列。
    (1) 初始化只有n个顶点的无
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值