《DSAA》 9.5.2 Kruskal 算法

如何用最少的电线给一所房子安装电路?本质上就是如何从一个无向图中找出一颗最小生成树。一个无向图中的最小生成树由该图的那些连接所有顶点的边构成的树,且其总价值最小。

有两个解决此问题的算法:Prim 和 Kruskal,这里只讨论后者,因为它比较简明有趣。

和一般处理图的算法不同,Kruskal 实际上是在处理森林,即树的集合,开始时每个顶点是一颗单节点树,添加一条边则意味着将两颗树合并成一棵树,添加边的顺序是从小到大,当边数比总顶点数小1时算法终止,这时就只有一颗树了,这颗树就是最小生成树。

但还有一个关键的问题是在添加边之前要对其进行检验,看看它是否会同已有的边构成回路,如是必须放弃这条边,否则将导致算法失败。检验的方法是使用一个不相交集合,当两个顶点在当前森林中连通时,它们必属于同一集合,所以当要添加边的两个顶点属于同一集合时,则放弃这条边。

btw,不相交集合在《DSAA》前面的章节讲过,它主要有两个方法:Union() 和 Find(),前者用于合并两个不相交集合,后者返回给定元素所在的集合,这里不赘述。

也是根据原书的伪代码做了实现,大致思路如下:

1)将全部的边装入一个二叉堆,按照权值从小到大排序

2)从堆中取出最小的边,如果其两个顶点不属于同一集合,则边数加1,合并这两个集合。否则什么也不做

3)重复第二步直到边数比总顶点数小1

下面是对原书中示例的求解,运行结果如下:




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值