一个连通图可能有多棵生成树,而最小生成树是一副连通加权无向图中一颗权值最小的生成树,它可以根据Prim算法和Kruskal算法得出,这两个算法分别从点和边的角度来解决。

Prim算法

  1. 输入:一个加权连通图,其中顶点集合为V,边集合为E;
  2. 初始化:Vn = {x},其中x为集合V中的任一节点(起始点),Enew = {};
  3. 重复下列操作,直到Vn = V:(在集合E中选取权值最小的边(u, v),其中u为集合Vn中的元素,而v则是V中没有加入Vn的顶点(如果存在有多条满足前述条件即具有相同权值的边,则可任意选取其中之一);
    将v加入集合Vn中,将(u, v)加入集合En中;)
  4. 输出:使用集合Vn和En来描述所得到的最小生成树。
以下面这张图作为例子,表格中的Vertex、Kown、Cost、Path分别表示顶点信息、是否访问过,权值,到达路径;
我们随机的选择顶点0作为起点,其执行步骤为:
步骤 选中结点
顶点0作为起始点 0
根据(6, 7, 8)的方案选中6 1
根据顶点1能够到达的权值(7, 4, 3)和顶点0能够到达的权值(7, 8)中选择3 5
根据顶点5能够到达的权值(8)和根据顶点1能够到达的权值(7, 4)和顶点0能够到达的权值(7, 8)中选择4 6
根据顶点6能够到达的权值(6, 7)和顶点0能够到达的权值(7)中选择6 2
根据顶点0能够到达的权值(7)和顶点6能够到达的权值(7)中选择7 4
根据顶点6能够到达的权值(7)选择7 7
根据顶点7能够到达的权值(2)选择2 3
全部结点都访问过,退出  

最终得到下面的结果,其中Path中的-1表示其作为起始点;

Prim算法实现

根据前面的那幅图来实现,如下:

class MST(object):def __init__(self, graph):self.graph = graphself.N = len(self.graph)passdef prim(self, start):index = startcost, path = [0] * self.N, [0] * self.N# 初始化起点known = [x for x in map(lambda x: True if x == start else False, [x for x in range(self.N)])]path[start] = -1for i in range(self.N):cost[i] = self.graph[start][i]# 遍历其余各个结点for i in range(1, self.N):mi = 1e9# 找出相对最小权重的结点for j in range(self.N):if not known[j] and mi > cost[j]:mi, index = cost[j], j# 计算路径值for j in range(self.N):if self.graph[j][index] == mi:path[index] = jknown[index] = True# 更新index连通其它结点的权重for j in range(self.N):if not known[j] and cost[j] > self.graph[index][j]:cost[j] = self.graph[index][j]print(path)
# 图用临接矩阵表示
MST([[1e9, 6, 8, 1e9, 7, 1e9, 1e9, 1e9],[6, 1e9, 7, 1e9, 1e9, 3, 4, 1e9],[8, 7, 1e9, 1e9, 1e9, 1e9, 6, 1e9],[1e9, 1e9, 1e9, 1e9, 1e9, 1e9, 1e9, 2],[7, 1e9, 1e9, 1e9, 1e9, 1e9, 1e9, 1e9],[1e9, 3, 1e9, 1e9, 1e9, 1e9, 1e9, 9],[1e9, 4, 6, 1e9, 1e9, 1e9, 1e9, 7],[1e9, 1e9, 1e9, 2, 1e9, 9, 7, 1e9],
]).prim(0)

path结果为:[-1, 0, 6, 7, 0, 1, 1, 6]

Kruskal算法

构造一个只含n个顶点,而边集为空的子图,若将该子图中各个顶点看成是各棵树的根节点,则它是一个含有n棵树的森林 。之后,从图的边集中选取一条权值最小的边,若该边的两个顶点分属不同的树 ,则将其加入子图,也就是这两个顶点分别所在的 两棵树合成一棵树;反之,若该边的两个顶点已落在同一棵树上,则不可取,而应该取下一条权值最小的边再试之。依次类推,直至森林只有一棵树。kruskal算法能够在并查集的基础很快的实现。

以下面这张图作为例子,其中左边的表格是一个并查集,表示可以连通的结点。我们首先要根据权值对每条边进行排序,接着开始处理每一条边的情况。

最终得到下面的结果图:

Kruskal算法实现

因为我们要处理边,所以需要建立边的数据结构,并且要从给定的图中获取每一条边的数据。

class Edge(object):def __init__(self, start, end, weight):self.start = startself.end = endself.weight = weightdef getEdges(self):edges = []for i in range(self.vertex):for j in range(i+1, self.vertex):if self.graph[i][j] != 1e9:edge = Edge(i, j, self.graph[i][j])edges.append(edge)return edges

接下来就是kruskal函数:

def kruskal(self):union = dict.fromkeys([i for i in range(self.vertex)], -1)  # 辅助数组,判断两个结点是否连通self.edges = self.getEdges()self.edges.sort(key=lambda x: x.weight)res = []def getend(start):while union[start] >= 0:start = union[start]return startfor edge in self.edges:# 找到连通线路的最后一个结点n1 = getend(edge.start)n2 = getend(edge.end)# 如果为共同的终点则不处理if n1 != n2:print('{}----->{}'.format(n1, n2))(n1, n2) = (n2, n1) if union[n1] < union[n2] else (n1, n2)union[n2] += union[n1]union[n1] = n2res.append(edge)print(union.values())

其中union打印出来的结果和图中是一致的,为[3, 3, 5, 6, 6, 6, -8, 3]。

最小生成树之Prim算法和Kruskal算法相关推荐

  1. 求的带权图最小生成树的Prim算法和Kruskal算法

    求的带权图最小生成树的Prim算法和Kruskal算法 最小生成树的概念 最小生成树其实是最小权重生成树的简称. 一个连通图可能有多个生成树.当图中的边具有权值时,总会有一个生成树的边的权值之和小于或 ...

  2. 【最小生成树】Prim算法和Kruskal算法的区别对比

    Prim算法和Kruskal算法都是从连通图中找出最小生成树的经典算法- 从策略上来说,Prim算法是直接查找,多次寻找邻边的权重最小值,而Kruskal是需要先对权重排序后查找的- 所以说,Krus ...

  3. 加权无向图与最小生成树(Prim算法和Kruskal算法)

    目录 0 引入 1 图的最小生成树定义及相关约定 2 最小生成树原理 2.1 性质 2.2 切分定理 3 贪心思想 4 Prim算法 4.1 算法步骤 4.2 API设计 4.3 Java代码演示 5 ...

  4. 最小生成树的prim算法和kruskal算法

    <span style="font-size:18px;">#include "stdafx.h" #include <iostream> ...

  5. 作业1-采用Prim算法和Kruskal算法构造最小生成树

    采用Prim算法和Kruskal算法构造最小生成树 实验报告 1.问题 2.解析 (1)Prim算法 (2)Kruskal算法 3.设计 (1)Prim算法 (2)Kruskal算法 4.分析 (1) ...

  6. Prim算法和Kruskal算法

       Prim算法和Kruskal算法都能从连通图找出最小生成树.区别在于Prim算法是以某个顶点出发挨个找,而Kruskal是先排序边,每次选出最短距离的边再找. 一.Prim(普里姆算法)算法: ...

  7. 【Java数据结构与算法】第十九章 贪心算法、Prim算法和Kruskal算法

    第十九章 贪心算法.Prim算法和Kruskal算法 文章目录 第十九章 贪心算法.Prim算法和Kruskal算法 一.贪心算法 1.介绍 2.支付问题 二.Prim算法 1.最小生成树 2.介绍 ...

  8. matlab实现prim算法,Prim算法和Kruskal算法的Matlab实现

    Prim算法和Kruskal算法的Matlab实现 <计算机仿真>期末大作业 Prim算法和Kruskal算法的Matlab实现 05605刘禹050697(30) 连线问题应用举例: 欲 ...

  9. 【数据结构】最小生成树问题(Prim算法和Kruskal算法)

    相关概念 连通图与它的生成树 连通图的生成树是包含图中全部顶点的一个极小连通子图.若图的顶点数为n,则它的生成树含有n-1条边.一个连通图可能拥有多个生成树. 最小生成树(Minimum-Spanni ...

最新文章

  1. CSS 相对|绝对(relative/absolute)定位系列(一)
  2. 监控ui_做了10年监控系统,有些经验想和你分享
  3. SpringMVC学习(二)——快速搭建SpringMVC开发环境(注解方式)
  4. 12c创建为容器数据库_oracle 12c创建可插拔数据库(PDB)与用户详解
  5. 谷歌发布android+8.2,谷歌Pixel 2代三款新机齐曝光:骁龙835+Android 8.0
  6. Java LocalDate类| 带示例的getDayOfYear()方法
  7. 梅森素数为什么这么重要?
  8. Godaddy Windows主机组件支持情况
  9. GNU C内嵌汇编学习笔记
  10. 制造-销售”模式正在消亡,传统大型企业的上云之路要如何举步?
  11. numpy-np.concatenate
  12. UVA 299 - Train Swapping(冒泡排序)
  13. 美女老师,大数据直播,老师做了什么,让全场尴尬。
  14. 这几个小众软件能支持英文文档翻译成中文
  15. jQuery实现打地鼠游戏
  16. Mac字体怎么安装?如何在macOS电脑导入字体文件?
  17. 弘辽科技:如何书写淘宝直通车创意标题才能带来更多的流量?
  18. 微擎人人商城 后台开启WAP访问后 微信浏览器 跳过授权 手机号密码登录
  19. 元芳, 我在 Win10 上用 Docker 肝了个 LNMP , 康康?
  20. 如何在 Linux 下关闭 i386 架构

热门文章

  1. python如何查看函数的参数_python 如何查看自带函数的默认参数?
  2. 6. ZigZag Conversion [Medium]
  3. css 字间距离 段落字符间距设置
  4. Java 对象排序 Comparable接口和比较器Comparator的使用
  5. 小满nestjs(第十九章 nestjs 管道验证DTO)
  6. 2021年电工(技师)答案解析及电工(技师)考试平台
  7. 数据结构实验之——哈夫曼树的实现
  8. 制作initrd.img
  9. 《数学分析》即《实变函数论》笔记(序)
  10. Vue进阶(四十五):精解 ES6 Promise 用法