求无向图的最小生成树——Kruskal算法(超详细)【并查集,python实现】

这篇具有很好参考价值的文章主要介绍了求无向图的最小生成树——Kruskal算法(超详细)【并查集,python实现】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、题目

以如下无向图为例,求最小生成树及其权值。求无向图的最小生成树——Kruskal算法(超详细)【并查集,python实现】
补充知识点:
最小生成树(不官方的解释):包含所有节点,保持整个图连通,所有边权值之和最小。

二、思路

1、补充在前

(1)图的存储

采用二维列表存储(点,点,边的权值)

# 由图我们得到的信息
edges = [['A', 'B', 2], ['A', 'D', 5], ['A', 'F', 8],
         ['B', 'C', 7], ['B', 'D', 7], ['B', 'E', 2],
         ['C', 'E', 3], ['D', 'E', 6], ['D', 'F', 7],
         ['D', 'G', 3], ['E', 'G', 4], ['F', 'G', 4]]
(2)顶点转换

为了便于计算,将字母A ~ G用数字0 ~ 6代替(这里可以使用字典实现)

# 字典key:value值
di = {0: 'A', 1: 'B', 2: 'C', 3: 'D', 4: 'E', 5: 'F', 6: 'G'}
# 顶点和边的关系转换如下
edges = [[0, 1, 2], [0, 3, 5], [0, 5, 8],
         [1, 2, 7], [1, 3, 7], [1, 4, 2],
         [2, 4, 3], [3, 4, 6], [3, 5, 7],
         [3, 6, 3], [4, 6, 4], [5, 6, 4]]

2、Kruskal算法思想

【画出所有节点(n 个),不加边】—> 【将边按权值由小到大排列】—> 【依次加上每一条边,判断加上该边后是否形成闭环,若形成闭环,则去掉该边;若不形成,则不动,继续下一条边的判断,直到图中一共加了 n - 1 条边,结束】
那么我们该怎么判断加上一条边后是否形成闭环呢?
画图我们很容易看出有没有形成闭环,重点是怎么利用代码实现这个过程,这就要用到下面的并查集了(说实话,我第一次遇到并查集这个概念的时候是很懵的,记得当时搞了好久才把这个思路理清楚,过程曲折且痛苦。。。)

3、并查集模板

(1)初始化父节点

初始化每一个顶点的父节点都自己(因为最开始一条边都还没有加上的时候,每一个顶点之间还没有联系)`

# 初始化n个节点的 fa(父节点)
# 这里的下划线和变量 i 同理
fa = [_ for _ in range(n)]
(2)查询父节点——查
# 查找当前元素所在树的根节点(代表元素)
def found(node):
	# 如果父节点就是自己,代表已经找到,直接返回即可
    if fa[node] == node:
        return node
    else:
        # 如果父节点不是自己,那就往上找一层,找父节点的父节点
        # 递归下去一定能找到
        fa[node] = found(fa[node])
        return fa[node]
(3)合并两节点所在集合——并
# 合并元素 node1, node2 所处的集合
def unite(node1, node2):
	# 先找两个节点的父节点
    node1 = found(node1)
    node1 = found(node1)
    # 如果父节点都一样,说明已经在一个集合中,不能再合并了
    if node1 == node2:
        return False
    else:
        # 统一两顶点的父节点,能合并
        fa[node1] = node2
        return True

三、完整实现及结果

def Kruskal(n, m, edges):
    # 按边权值排序
    edges.sort(key=lambda edges: int(edges[2]))

    # 初始化边数和放置边数的集合
    edge_num = 0
    res = []

    # 遍历每一条边
    for i in range(m):

        # 先判断,边数 = n - 1 就结束
        if edge_num == n - 1:
            break

        # 判断能否合并(能合并,证明不成环)
        if unite(edges[i][0], edges[i][1]):
            res.append(edges[i])
        edge_num += 1
    return res


# 查找当前元素所在树的根节点(代表元素)
def found(node):
    if fa[node] == node:
        return node
    else:
        fa[node] = found(fa[node])
        return fa[node]


# 合并元素 node1, node2 所处的集合
def unite(node1, node2):
    node1 = found(node1)
    node1 = found(node1)
    if node1 == node2:
        return False
    else:
        fa[node1] = node2
        return True


m = 12  # 边数
n = 7  # 顶点个数
di = {0: 'A', 1: 'B', 2: 'C', 3: 'D', 4: 'E', 5: 'F', 6: 'G'}

fa = [_ for _ in range(n)]

# 顶点和边的关系
edges = [[0, 1, 2], [0, 3, 5], [0, 5, 8],
         [1, 2, 7], [1, 3, 7], [1, 4, 2],
         [2, 4, 3], [3, 4, 6], [3, 5, 7],
         [3, 6, 3], [4, 6, 4], [5, 6, 4]]
res = Kruskal(n, m, edges)
# 打印最终点边关系
s = 0
for edge in res:
	# 这里箭头只代表两顶点之间的连接作用,与方向无关
    print(f'{di[edge[0]]}->{di[edge[1]]}: {edge[2]}')
    s += edge[2]
print(f'权值:{s}')

结果展示:
求无向图的最小生成树——Kruskal算法(超详细)【并查集,python实现】
最后,如果哪里写的有问题,欢迎大家指出来哦,共勉。(如有侵权,可联系改正/删除)文章来源地址https://www.toymoban.com/news/detail-442779.html

到了这里,关于求无向图的最小生成树——Kruskal算法(超详细)【并查集,python实现】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 算法提升:图的最小生成树算法-克鲁斯卡尔(Kruskal)

    目录 概念 思路 代码 克鲁斯卡尔算法查找最小生成树的方法是:将连通网中所有的边按照权值大小做升序排序,从权值最小的边开始选择,只要此边不和已选择的边一起构成环路,就可以选择它组成最小生成树。对于 N 个顶点的连通网,挑选出 N-1 条符合条件的边,这些边组

    2024年02月03日
    浏览(27)
  • 5G网络建设--并查集--最小生成树

    题目描述 现需要在某城市进行5G网络建设,已经选取N个地点设置5G基站,编号固定为1到N,接下来需要各个基站之间使用光纤进行连接以确保基站能互联互通,不同基站之间假设光纤的成本各不相同,且有些节点之间已经存在光纤相连。 请你设计算法,计算出能联通这些基站

    2024年04月17日
    浏览(42)
  • Java高阶数据结构 & 并查集 & 最小生成树

    并查集与最小生成树 1.1 并查集的原理 在一些应用问题中,我们常常会遇到一类问题 一开始是一个人 后来新增的人可能与这个人有关系,也可能与这个人无关系。 一个人与一个人有关系,这个人与另一个人也有关系,那么三人都有关系。 有关系的和没关系的之间是不同的类

    2024年02月03日
    浏览(28)
  • 【算法导论】图论(图的基本概念,图上的深度优先搜索(DFS),广度优先搜索(BFS),最小生成树(MST)及Prim,Kruskal算法)

    图(Graph)是一种包含节点与节点的边的集合,记作G=(V,E),V是节点的集合,E是边的集合。 有向图 一个有向图G=(V,E),E中每个元素是V上的一个二值关系:一条从a出发的连向b的边e可以记作一个 有序 对e = (a,b) 。 无向图 一个无向图G=(V,E),E的每个元素e可以表示V上的一个 无序 对,记

    2024年02月03日
    浏览(32)
  • 已知无向图G如下所示,使用普里姆 (Prim)算法求图G的最小生成树。 (a)请写出从顶点T出发,加到最小生成树中的边次序。 (6分) (2)说明Prim算法更适用于求哪种类型无向图的最小生 成树。(2分) (3)当图中顶点个数为n,边的个数为e时,该算法

    (a)从顶点T出发,加到最小生成树中的边次序如下: 先加入顶点T到顶点E的边,得到的最小生成树为:T-E 再加入顶点E到顶点D的边,得到的最小生成树为:T-E-D 再加入顶点D到顶点B的边,得到的最小生成树为:T-E-D-B 再加入顶点B到顶点C的边,得到的最小生成树为:T-E-D-B-C 再加

    2024年01月17日
    浏览(31)
  • 最小生成树——Kruskal算法

    目录 基本思想 实现 伪代码 实际问题求解 最小生成树 :带权连通图的生成树中 边的权值之和最小的生成树。 最小生成树不是唯一的。当图中的各边权值互不相等时,最小生成树是唯一的; 若无向连通图本身是一棵树时(边数比顶点数少1 ),则最小生成树就是它本身。 最

    2023年04月26日
    浏览(35)
  • Kruskal 算法 最小生成树

    1.按边从小到大进行排序 2.从小到大进行加边,保证加入的边的两端点不连通,即保证不形成回路

    2024年02月10日
    浏览(30)
  • 最小生成树——Kruskal算法详解

    1.Kruskal算法解决问题 :最小生成树 2.Kruskal所需要的前提知识: 边集数组(引用)和 结构体 3.Kruskal算法主要思想: Kruskal算法将 n 个点看成 n 个独立的连通分支。 首先按边权大小排序。 然后只要在 m 条边里按 下表从小到大遍历 选出 合适 的 n - 1 条(前提条件:选出的边不

    2024年02月03日
    浏览(25)
  • Kruskal算法求解最小生成树

    最小生成树是一个连通图。 什么是连通图,(强)连通图详解 前面介绍了《图存储结构》,本节继续讲解什么是 连通图 。 前面讲过,图中从一个顶点到达另一顶点,若存在至少一条路径,则称这两个顶点是连通着的。例如图 1 中,虽然 V1 和 V3 http://c.biancheng.net/view/3405.ht

    2024年02月07日
    浏览(44)
  • 最小生成树(Prim算法,Kruskal算法)

    (1)生成树: 如果在一个无向连通图不包含回路(连通图中不存在环),则为一个树 (2)最小生成树(minimal spanning tree): 在一个图所有生成树中,代价最小的生成树称为最小生成树 (3)生成树的代价: 在一个无向连通网中,生成树各边的权值之和称为该生成树的代价

    2024年02月08日
    浏览(25)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包