Keruskal 算法

导入

自从上次与最小生成树们玩了一上午的捉迷藏,他们就决定不让你使用Prim算法来找他们(因为Prim算法实在是太好用了,让他们连输了好几把),现在,为了挽回你们脆弱的友谊,你只能换一种算法了,那么到底该用什么算法呢?

Keruskal 算法

于是你找来了Prim算法的好兄弟,今天的主角----- Keruskal 算法

算法描述

与Prim算法相同,Keruskal算法也是一中使用贪心的策略,在加权连通图中求最小生成树的算法

两者都使用了贪心的策略,同样的都能求出加权连通图中的最小生成树,那么,他们究竟有什么不同之处呢?

与prim算法的不同之处

想要理解Prim算法与Keruskal算法之间的关系,我们首先要明白两个算法的实现方式(即使用了什么样的方法来找出最小生成树)

Prim算法的方法是,寻找与dist集合距离最近的顶点,并将这个点标记加入到dist集合当中,从而找出最小生成树

Keruskal算法的方法则是,将每一条边按边权升序排序,然后找出能将两个集合相连的边权最小的边,从而达到找出最小生成树的目的

让我们看图说话,这是一个图,此时每个顶点的父都是自己
在这里插入图片描述

现在,我们通过贪心,找到了一些边权较小的边,然后把他们合成一个集合

在这里插入图片描述
可是接下来该选哪一条边呢,这个时候就要开始选择能把两个集合联系在一起的边了,没错,就是选择1-5 这一条边

在这里插入图片描述
以此类推,最后得到的集合就是最小生成树了

相信从两个算法实现的方法,我们也能看得出来,这两个算法有着很大的区别

算法实现

了解了这些不同后,我们就可以着手来尝试实现Keruskal算法了
不过,你真的了解并查集吗?

回顾并查集

刚才在描述Keruskal算法的实现过程时,我们提到了合并两个集合,那么,两个集合,是如何实现合并与查找的呢?

并查集—合并操作

合并操作的目的,是将两个集合合并成一个集合,那么应该如何实现这个目的呢

其实很简单,在一个集合中,每个“子”,都有一个“父”,我们只需要改变这个集合中的“父”的“父”,让他变成最后合成出的大集合中的一个子

就像图中所表述的一样(红字是这个顶点的父)
在这里插入图片描述
按照我们刚才说的来做就好了
在这里插入图片描述

这就是并查集里的合并操作

并查集—查找操作

看完合并,我们再来看看查找
查找的目的是寻找到集合中的父(如下图,里面的父是顶点一)
在这里插入图片描述
很简单,我们只需要找到一个父为自己的点就行了

数据处理

回顾完并查集后,我们终于可以回到正轨,来实现Keruskal算法了

数据的处理上,我们新添加了一个数组mf用于记录每个点的父,同时不再使用和Prim以及Dijkstra算法的排序队列,而是直接使用数组edges来存储边的信息

struct Node{
   
	int n1,n2,w;//前驱,ID,边权
	Node(){
   }
	Node(int i,int d,int l){
   
		n1=i;n2=d;w=l;
	}
	friend bool operator < (Node a,Node b){
   
		return a.w<b.w;
	}
};  
Node edges[10000];
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值