没有合适的资源?快使用搜索试试~ 我知道了~
最小生成树Kruskal和Prim算法讨论.pdf
1.该资源内容由用户上传,如若侵权请联系客服进行举报
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
版权申诉
0 下载量 116 浏览量
2022-11-06
08:31:35
上传
评论
收藏 995KB PDF 举报
温馨提示
试读
16页
。。。
资源推荐
资源详情
资源评论
最小生成树的 Kruskal 和 Prim 算法讨论
By 张季伦
最小生成树的定义是在一个图 G(V,E)中,找到一个无回路的子集 T 属于 E,
使得 T 连通所有 V 中的顶点且 T 的边权值和最小。
有定义可知,由于 G`(V,T)没有回路,所以说它是一棵树;边子集 T 使得图
G 成为连通图,所以说 G`(V,T)生成了 G,所以说 G`(V,T)是一个生成树,由于边
权值最小,所以我们叫它最小生成树。
这次主要介绍最小生成树的生成算法,其中又包括 Kruskal 算法和 Prim 算法,
我将给出 Prim 算法的一个简单版本的源代码。
最小生成树的一个实际例子是离散城镇互通问题,其实可以模型化为无向图
的最小生成树问题,初始状态默认了所有城镇都是逻辑上可连通的,那么这是一
个强连通的无向图,然后我们的工作是找到一个方案使得最终修路时所用的材料
最少。也就是总路程长度最短,于是目标就是求这个图的最小生成树。
诶哟突然发现最小生成树和 Disjoint Set 的问题有点相似的,想了解 Disjoint
Sets 的娃儿可以去我的博客看看这一篇很早以前讨论 Disjoint Sets 的文章,写得
比较仔细。(传送门:http://luanluanqc.diandian.com/post/2012-05-08/19418773)
如果你已经稍微懂了最小生成树(Minus Spanning Tree)的概念的话,那让
我们来看看怎么从一个无向图中找到它的 MST。
首先,你要知道一个确定的无向图的 MST 可能是不确定的,也就是可能有
两个不同的生成树然而它们的总权重确实最小且相等的。
然后,我们抛开一切关于计算机实际实现的过程,想一想以最原始的方法如
何求得一个无向图的最小生成树。
好吧,我知道一个图 G(V,E)的 MST 是这样定义的 T(V,E`),MST 与其
图的顶点域是相同的,但是 E`却是 E 的一个子集。于是我这样描述一个求 MST
的原始算法:
我首先定义一个边集合 T,这个 T 在这时是空集。
然后,我向 T 中放入满足如下条件的边 e:
e 满足,当 e 被加入 T 后,T 仍然是一个最小生成树的子集。
当集合 T 顶点集合等于图的顶点集合时,算法运行结束。
这个算法其实只是确定了一个策略,那就是通过不断的向目标结合增加边来
生成最小生成树。而关于接下来的实现的难点就是:我们如何定义“添加进集合
后仍然使集合为最小生成树的子集的边”所拥有的特征。
下面我引入书中的定理加上自己归纳出的一套规则来说明这种特殊的边的
性质,然后我将证明我们算法的正确性。
首先,假设集合 T 已经为空集,这是算法开始时的情况,我们知道,这个图
必然是有最小生成树的,所以说这第一条边必然存在。然后,当 T 集合的顶点
集合还未和 E 相等时,说明循环不变式仍未结束。所以还存在可以添加进 T 的
边。
到了证明边的特性的时候了,一个最小生成树算法的实例已经运行到了普遍
的循环不变式阶段(意味着 T 的点集不为空也不等于 E),这时,我们需要向集
合中添加一条边。
下面就是我自己的一套了“紧缩规则”了,我把已经成为最小生成树的子集
的那部分顶点和边看作一个整体(或者说一个顶点,将它们紧缩成一点),那么
其他的有和这个顶点相连通的顶点所构成的边我把它称为“跨越”子集的边,同
时也可以知道,集合里很正常的会出现“非跨越某一集合”边。通俗的来讲,“跨
越集合的边”会让该集合变大(边数加一,顶点数加一)。
我们要添加进最小生成树子集的顶点(或者边)必须是“跨越”子集 T 的。
然后,如何来确定我们添加进子集的边一定是一课最小生成树的边呢?这时使用
贪心策略是一个好的办法。确保每一次添加进子集的便都是当前满足“跨越”原
则的边中最小的。
这样,每次添加的边就都是属于最小生成树的了。在书中,称这样的边为“轻
边”或者“安全边”。
可以看到,我们用了贪心策略,“每一次子决策都是当前决策集中的最优决
策,会生成一个较优的结果”。后面我会证明在最小生成树生成算法中,这个“较
优”的结果,也是“最优”的。
下面我们来关心具体的实现了,来讨论两个对于图的最小生成树生成的经典
算法 Kruskal 算法和 Prim 算法。这两个算法的策略都是基于我们刚才讨论的“原
始”算法,只不过一个是基于向已知集合添加边,一个是添加点(不过实际它们
没区别)。另一个区别就是 Kruskal 在生成树生成过程中是由森林生成的(Union
Forest),而 Prim 将从一个随机的 Root 开始,最终生成一课 MST,这个过程中,
子集 T 呈现一个生长的姿态。
首先是 Kruskal 算法,我不会给出 Kruskal 的源代码,因为实现 Krukal 还需
要一些现成的数据结构,如果全部实现的话有点累赘,也偏离了讨论 MST 的初
衷。而正是因为 Kruskal 实际实现的程度。它在算法策略比 Prim 要简单。
下面是 Kruskal 的伪代码实现:
KRUSKAL_MST(GRAPH G){
NEW SET(T);
//v is Empty
SORT(G.E)UNINCREASING WITH WEIGHT;
FOR EACH E(v,u) IN INCREASING WITH WEIGHT
IF (SET(v)==SET(u)) CONTINUE;
ELSE UNION(T.V,v,u);
UNION(T.E,(v,u));
RETURN T;
}
注意蓝色字体的判断过程,由于最小生成树种不存在环,由于如果两个顶点
属于同一个集合那么就会产生一个一个环(回路)。当然这是针对同一条边的两
个顶点来做的。
Kruskal 算法时间花费主要耗费在将边权值做一个排序的操作上,可以看到
在后面的 for 循环中,如果判断同一集合的方法能够利用线性表的索引特性也会
降低复杂度。
下面的例子描述了 Kruskal 算法的运行过程(感谢度娘盗的维基的这些图,我
不用重新做图了):
1.初始状态,将边排序
2.开始向 T 中加入边,升序加入,首先加入AD,权值为 5。
3.继续运行循环不变式,不过要开始注意判断是否形成环路。找
到了另一条权值为 5 的 CE 边(非环路)
剩余15页未读,继续阅读
资源评论
G11176593
- 粉丝: 6643
- 资源: 3万+
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功