最小生成树,Prim算法与Kruskal算法,408方向,思路与实现分析

最小生成树,Prim算法与Kruskal算法,408方向,思路与实现分析

最小生成树,老生常谈了,生活中也总会有各种各样的问题,在这里,我来带你一起分析一下这个算法的思路与实现的方式吧~~

在考研中呢,最小生成树虽然是只考我们分析,理解就行,但我们还是要知道底层是怎么实现的,话不多说,进入正题~~

什么是生成树?什么是最小生成树

总所周知,对于一个无向连通图,我们想把他看成一个树的话,那么就不能太乱,也就引出了,如果对于一个生成树(不唯一,满足条件即可),如果砍去它的一条边,则会变成非连通图,如果加上一条边则会形成一个回路,也就是包含图的全部顶点的一个极小连通子图,如下所示~~

图片
因此,对于顶点数为n的图,生成树应含有n-1条边~~

那么,最小生成树又是什么呢?

当边带权时,我们想要一个生成树,使得带权路径和最小,那么这样的生成树就被我们称作最小生成树(不唯一),也就是边的权值之和最小的生成树(MST,Minimum-Spanning-Tree)~~

那么怎么求一个最小生成树呢?

没错,我们相求一个最小生成树,我们的前辈大牛也想过这个问题,也就引出了两个算法,一个是Prim算法(普里姆),和Kruskal算法(克鲁斯卡尔)~~

先给一个案例我们来分析一下,经典的修路~~

我们想要使得我们这个小镇全都连通,但又花费经济最少(虚线边数值代表所需金钱,也就是权值),该怎么修呢?先给出答案,接下来我们用两个算法分别分析一下思路以及底层实现~~

图片

Prim算法(普里姆)思路分析与底层实现

Prim算法:从选取的某一个顶点开始,每次将代价最小的新顶点纳入生成树,直到所有顶点都纳入为止~~

思路分析:也就是并查集内加新顶点,为了方便理解,我们把并查集每次都纳入的顶点看成一个在一个圈里加入新顶点,不属于圈里的即为连通的顶点,如图所示算法思路~~

图片

底层实现:我们这里定义两个数组一个为isJoin[]和lowCost[]数组,isJoin[]用来标记是否已加入树,lowCost[]用来表示各节点加入当前树时的最低代价~~

如第一个步骤的时候,只有c点加入了树,那么我们就当c点已经加入了树,也就是说isJoin[6]变为了如表所示(为了方便我们把数组下标换成我们的字母abcdef)~~

CABDEF
isJoin[6]100000

此时我们的lowCost[6]对应就应为(没有边直接连通则为无穷):

CABDEF
lowCost[6]015464

lowCost最小为1,也就是C与A连接所需代价最小,所以当第1步结束时,我们将A连入树中,修改对应isJoin[6]和lowCost[6]~~

CABDEF
isJoin[6]110000
CABDEF
lowCost[6]005464

权:1~~

lowCost最小为4,也就是(D或者F)与圈AC连接所需代价最小,所以当第2步结束时,我们将F连入树中,修改对应isJoin[6]和lowCost[6]~~

CABDEF
isJoin[6]110001
CABDEF
lowCost[6]005260

权:1+4~~

因为现在要和圈ACF连接,D如果想代价最小就可以选择DF连接(2),而不是以前的DC连接(4),2代价更小,这就是lowCost[]用来表示各节点加入当前树时的最低代价的意思~~

重复此过程~~

CABDEF
isJoin[6]110101
CABDEF
lowCost[6]005060

权:1+4+2~~

接下来

CABDEF
isJoin[6]111101
CABDEF
lowCost[6]000030

权:1+4+2+5~~

最后

CABDEF
isJoin[6]111111
CABDEF
lowCost[6]000000

权:1+4+2+5+3=15~~

Kruskal算法(克鲁斯卡尔)思路分析与底层实现

双生关系,Prim是每次选一个连到树里代价最小的顶点构成一个树,Kruskal是每次选一条权值最小的边,使这条边两端连通(如果原本就已经连通就不选),直到所有结点都连通~~

思路分析:上图~~

图片

底层实现:并查集~~

按权值排序~~

weight12
1AC
2DF
3BE
4DC
4CF
5AD
5BC
6AB
6CE
6EF

依次往下看,1和2两个点是否属于同一集合(先规定所有顶点都属于不同的集合,如果两个顶点相连,则这两个顶点构成了一个集合)~~

如第一次,weight为1,A和C为不同集合,相连,通过~~(集合AC,B,D,E,F)

第二次,weight为2,D和F为不同集合,相连,通过~~(集合AC,DF,B,E)

第三次,weight为3,B和E为不同集合,相连,通过~~(集合AC,DF,BE)

第四次,weight为4,D和C虽然DF是一个集合,AC是一个集合,但DF和AC不是一个集合里的不连通,所以相连,通过~~(集合ACDF,BE)

第五次,weight为4,C和F同属于ACDF集合里,所以不相连,不通过~~(集合ACDF,BE)

第六次,weight为5,A和D同属于ACDF集合里,所以不相连,不通过~~(集合ACDF,BE)

第七次,weight为5,B和C不属于同一个集合里,所以相连,通过~~(集合ABCDEF)

至此成功~~

最小生成树还是简单的,为我们后面学习最短路径做基础,这里大家好好看看,下周我就来谈一谈最短路径的几个算法,这两者很像,但要区分开来~~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Prim算法Kruskal算法都是求解图的最小生成树问题的经典算法,它们的思想和实现方法不同,下面是它们的实验小结。 1. Prim算法 Prim算法是一种贪心算法,它从图的某个点开始,逐步扩展生成树,直到生成整个图的最小生成树算法步骤如下: 1.1 选取任意一个点作为起始点,将该点加入生成树中。 1.2 找到与当前生成树相连的边中,权重最小的边,将其连接的点加入生成树中。 1.3 重复步骤1.2,直到生成整个图的最小生成树Prim算法的时间复杂度为O(E log V),其中 E 表示边的数量,V 表示点的数量。Prim算法的优点是实现简单,适用于稠密图;缺点是不适用于稀疏图。 2. Kruskal算法 Kruskal算法也是一种贪心算法,它从图的所有边开始,逐步扩展生成树,直到生成整个图的最小生成树算法步骤如下: 2.1 将图中所有边按照权重从小到大排序。 2.2 依次选择每条边,判断该边的两个端点是否在同一连通块中,如果不在,则将它们合并,并将该边加入生成树中。 2.3 重复步骤2.2,直到生成整个图的最小生成树Kruskal算法的时间复杂度为O(E log E),其中 E 表示边的数量。Kruskal算法的优点是适用于稀疏图;缺点是实现相对复杂。 综上所述,Prim算法Kruskal算法都是求解图的最小生成树问题的有效算法,选择哪种算法主要取决于图的性质和算法实现的难易程度。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

ZaunEkko

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

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

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

打赏作者

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

抵扣说明:

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

余额充值