最小生成树的两个算法之二:kruskal算法

24 篇文章 2 订阅
5 篇文章 0 订阅

介绍kruskal算法之前需要了解一个很重要的数据结构:并查集  参考博文:https://www.cnblogs.com/yoke/p/6697013.html

基本概念

树(Tree):如果一个无向连通图中不存在回路,则这种图称为树。
生成树 (Spanning Tree):无向连通图G的一个子图如果是一颗包含G的所有顶点的树,则该子图称为G的生成树。
生成树是连通图的极小连通子图。这里所谓极小是指:若在树中任意增加一条边,则将出现一条回路;若去掉一条边,将会使之变成非连通图。
最小生成树(Minimum Spanning Tree,MST):或者称为最小代价树Minimum-cost Spanning Tree:对无向连通图的生成树,各边的权值总和称为生成树的权,权最小的生成树称为最小生成树。
构成生成树的准则有三条:
<1> 必须只使用该网络中的边来构造最小生成树。
<2> 必须使用且仅使用n-1条边来连接网络中的n个顶点
<3> 不能使用产生回路的边。
构造最小生成树的算法主要有:克鲁斯卡尔(Kruskal)算法和普利姆(Prim)算法他们都遵循以上准则。

Kruskal算法(并查集+贪心)

Kruskal算法的基本思想是以边为主导地位,始终选择当前可用(所选的边不能构成回路)的最小权植边。所以Kruskal算法的第一步是给所有的边按照从小到大的顺序排序。接下来从小到大依次考察每一条边(u,v)。
具体实现过程如下:
<1> 设一个有n个顶点的连通网络为G(V,E),最初先构造一个只有n个顶点,没有边的非连通图T={V,空},图中每个顶点自成一格连通分量。
<2> 在E中选择一条具有最小权植的边时,若该边的两个顶点落在不同的连通分量上,则将此边加入到T中;否则,即这条边的两个顶点落到同一连通分量上,则将此边舍去(此后永不选用这条边),重新选择一条权植最小的边。
<3> 如此重复下去,直到所有顶点在同一连通分量上为止。

把所有边排序,记第i小的边为e[i] (0<=i<m, m为边的个数) 
初始化MST为空 (MST为装载边的容器,选中的边会添加进MST)
初始化连通分量,使每个点各自成为一个独立的连通分量(用并查集实现)
for (int i = 0; i < m; i++){
    if (e[i].u和e[i].v不在同一连通分量){
       把边e[i]加入MST
       合并e[i].u和e[i].v所在的连通分量 
    } 
} 

并查集只需要一个parent数组、rank数组,和两个函数:合并、查询来构成。与之前介绍的有点细微不同的时,我们的parent数组进行了一个小小的改进。在原先的并查集介绍中,对于根节点,它的父节点就是本身,这样查询时可以判断该节点是否为根节点,但这个根节点的父节点本身的值没什么意义。这样很浪费资源,我们可以在保证查询操作能辨别它是根节点的同时,用根节点的父节点来存储更有用的信息!于是我们规定:对于所有的根节点,他们的父节点值是个负值,且负值的绝对值大小代表该树的节点数量。负值使得根节点和非根节点有所区别,而负值的大小则存储了树节点总数这一个很有用的信息。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值