图搜索算法-最小生成树问题-克鲁斯卡尔算法(kruskal)

相关文章:
数据结构–图的概念
图搜索算法 - 深度优先搜索法(DFS)
图搜索算法 - 广度优先搜索法(BFS)
图搜索算法 - 拓扑排序
图搜索算法-最短路径算法-戴克斯特拉算法
图搜索算法-最短路径算法-贝尔曼-福特算法

最小生成树

首先认识什么叫生成树(spanning tree),一个有N个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有N个结点,并且有保持图连通的最少的边,如图所示。
在这里插入图片描述

最小生成树(Minimum Spanning Tree)问题(下面简称MST)是指给定连接图G具有正的边权重,找到连接所有结点的边的最小权重集。MST应用场景多为网络设计,如光纤网络、燃气管道网络、电缆、道路交通等路线设计,其问题可以用克鲁斯卡尔(kruskal)算法或普里姆(prim)算法求解。

克鲁斯卡尔算法(kruskal)

这里有一个案例,一家公司在6个城市有分公司,他们之间需要用专用电话线路链接起来,电信公司给出了每个城市之间铺设线路的费用,如图所示。现在需要设计一个方案,用最少费用完成这个电话线路铺设。
在这里插入图片描述
面对这个问题,自然会想到尽量选择最小权重的边,结果必然是最小了。在算法里面,称为贪心算法。基本思想是通过获得局部的最优解,从而得到最终的最优解。现在要使用的克鲁斯卡尔算法核心思想是贪心算法,目标非常明确简单,步骤如下。
(1)初始化一个生成树集合(简称MST)为空。
(2)按边的权重由大到小进行排序。
(3)选择最小权重的边,检查它是否与MST形成一个循环图。如果没有形成循环图,则把该边放进MST,否则将其丢弃。
(4)重复步骤3,直到生成树中有(N-1)个边(N为结点数)。
分析步骤,克鲁斯卡尔算法最多遍历E条边,每次选择最小代价的边仅需要O(logE)的时间,因此,克鲁斯卡尔算法的时间复杂度为O(ElogE),空间上需要一个N-1空间记录最小生成树,所以空间复杂度为O(N)。现在尝试手动计算求解,首先是边权重的排序,结果如表所示。
在这里插入图片描述
然后选择权重最小的边【上海-武汉】,因此MST初始值为空,当然没有循环图,所以不存在循环图,当然把这条边放进MST中,接着挑选边【广州-成都】,同样也不存在循环图,如图所示。
在这里插入图片描述
用同样的方式,选择【广州-厦门】、【广州-武汉】都进入了MST,然后挑选【厦门-武汉】,这时候就形成了一个循环,因此丢弃此边,当前MST的状态如下图所示。
在这里插入图片描述
紧接着选择【厦门-上海】,同样也形成了循环,同样不能放到MST中。然后继续选择【北京-上海】,这条边则成功进入MST中,此时MST的边数量已经达到5个,满足结束条件,最终结果如下图6-8所示。此图也就是电话路线的铺设方案,总费用是MST上所有边的权重和为14。
在这里插入图片描述
用代码来表现此算法,首先知道这是一个有权无向图,则使用邻居列表并且带有权重,【Graph】类的输入不适用于这里,需要创建新的类叫【GraphPower】。

class GraphPower(): """有权图类"""def __init__(self, points):self.amount = len(points) # 记录结点的总数self.points = points      # 记录结点位置和值的关系self.graph = []           #  初始化图的邻接列表def add_edge(self, u, v, w):if u in self.points and v in self.points:index_u = self.points.index(u)index_v = self.points.index(v)self.graph.append([index_u, index_v, w]) # 录入数据else:print("录入数据有误")

算法的过程在此,创建【GraphKruskal】类,kruskalMST()函数是克鲁斯卡尔算法主体,然后用不相交集来检验是否有循环出现。

class GraphKruskal(GraphPower): """克鲁斯卡尔算法,输入的是有权无向图,求解最小生成树"""def find(self, parent, i):# 寻找其父结点if parent[i] == i: return i return self.find(parent, parent[i])def kruskalMST(self):# 基于不相交集实现克鲁斯卡尔算法主程序# 第一步初始化MST =[] # 初始化MST,也是最终结果 parent = [] # 初始化列表记录结点的相交连接结点下标,用于检测是否有循环for node in range(self.amount): # 每一个结点创建一个子集合 parent.append(node) index_sorted_edge = 0 # 根据权重已排序的边的下标 index_reslut = 0 # MST列表中的下标 # 第二步,根据权重排序self.graph = sorted(self.graph,key=lambda item: item[2]) # 权重w在item中的三个位置while len(MST) < self.amount -1 : # 结束条件:直到生成树中有(N-1)个边 # 第三步,选择最小权重的边u,v,w = self.graph[index_sorted_edge] index_sorted_edge = index_sorted_edge + 1# 检查它是否与MST形成一个循环图。如果没有形成循环图,则把该边放进MST,否则将其丢弃parent1 = self.find(parent, u) parent2 = self.find(parent ,v)if parent1 != parent2:MST.append([u,v,w])         # 结果中添加新的边parent[parent2] = parent1  # 更新不相交集self.print_result(MST)def print_result(self, result):print("输出最小生成树结果")total = 0for u,v,weight in result:total += weightprint ("{} -- {} == {}".format(self.points[u], self.points[v],weight))else:print("权重总和为:%d" % total)

用例子作为输入来验证结果,运行情况如下。

g = GraphKruskal(["广州","厦门","成都","武汉","上海","北京"]) 
g.add_edge("广州","厦门", 2)
g.add_edge("广州","武汉", 3) 
g.add_edge("广州","成都", 2) 
g.add_edge("武汉","厦门", 4) 
g.add_edge("武汉","成都", 8) 
g.add_edge("武汉","上海", 1) 
g.add_edge("武汉","北京", 9)
g.add_edge("厦门","上海", 5)
g.add_edge("成都","北京", 7)
g.add_edge("上海","北京", 6)
g.kruskalMST()
# ------------结果------------------
输出最小生成树结果
武汉 -- 上海 == 1
广州 -- 厦门 == 2
广州 -- 成都 == 2
广州 -- 武汉 == 3
上海 -- 北京 == 6
权重总和为:14

更多内容

想获取完整代码或更多相关图的算法内容,请查看我的书籍:《数据结构和算法基础Python语言实现》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/12641.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Redis】数据类型

Redis数据类型&#xff08;5 3 1&#xff09; 五种基本数据类型 String字符串 特点 二进制安全&#xff0c;可以包含任何数据&#xff0c;如数字&#xff0c;字符串&#xff0c;jpg图片或者序列化的对象 应用场景 缓存&#xff1a; redis作为缓存层&#xff0c;mysql做持…

【ORACLE战报】2024.4月最新OCP考试喜报.

课程介绍 DBA数据库管理必备认证&#xff1a;ORACLE OCP 19C 教材下载 ORACLE OCP 19C 官方电子教材 ORACLE OCP 12C官方电子教材 题库下载 ORACLE 19C题库 &#xff08;083384题、082362题&#xff09;-2024答案修正版.rar 所有的收获都是默默耕耘的成果 2024.4月【最新考试成…

Chromium 调试指南2024 Windows11篇-条件断点、函数断点(十一)

1. 前言 在调试过程中&#xff0c;步进代码和条件断点/函数断点是非常有用的工具和技术&#xff0c;它们可以帮助开发者更加精确地定位和解决问题。本文将介绍步进代码的常用工具以及条件断点/函数断点的设置方法&#xff0c;帮助开发者更加高效地进行调试工作。 2. 步进代码…

ControlNet原理解析

前排提示照片已经获得小姐姐许可。 光知道ControlNet好用&#xff0c;不想知道它背后的原理么&#xff1f;今天就看一看这篇论文&#xff0c;带大家了解一下ControlNet是如何炼成的。 ControlNet是干嘛的 我们知道现在文本到图像生成很火爆&#xff0c;你只需要输入文字就可以…

内存函数:memcpy(拷贝),memmove(拷贝),memcmp(比较),memset(设置)

内存函数 一.memcpy&#xff08;内存拷贝1&#xff09;1.函数使用2.模拟实现 二.memmove&#xff08;内存拷贝2&#xff09;1.函数使用2.模拟实现 三.memcmp&#xff08;内存比较&#xff09;1.函数使用2.模拟实现 四.memset&#xff08;内存设置&#xff09;1.函数使用2.模拟实…

【Linux】用户组、用户、文件权限(ugo权限),权限掩码,chmod,chown,suid,sgid,sticky,su,sudo

用户组 注意&#xff1a;普通用户只能查看有哪些组&#xff0c;不能创建/修改/删除&#xff0c;会提示&#xff1a;用户名 is not in the sudoers file.This incident will be reported. groupadd 用户组名新建用户组cat /etc/group查看有哪些组&#xff08;普通用户可以操作…

Windows下配置TortoiseGit 访问Ubuntu虚拟机下Samba共享目录

前言&#xff1a; 本文记录学习使用 Git 版本管理工具的学习笔记&#xff0c;通过阅读参考链接中的博文和实际操作&#xff0c;快速的上手使用 Git 工具。 本文参考了引用链接博文里的内容。 引用: 【TortoiseGit】TortoiseGit安装和配置详细说明-CSDN博客 Git版本管理可视…

Java——对象的打印

当我们运行如下代码&#xff1a; public class Person {String name;String gender;int age;public Person(String name,String gender,int age){this.name name;this.gender gender;this.age age;}public static void main(String[] args){Person person new Person(&quo…

QT客户端开发的注意事项

QT客户端开发是一个涉及图形用户界面&#xff08;GUI&#xff09;设计、网络编程、数据库交互等多个方面的复杂过程。以下是在进行QT客户端开发时应注意的一些关键事项&#xff0c;通过关注这些事项&#xff0c;可以提高QT客户端应用的质量和开发效率。北京木奇移动技术有限公司…

Eclipse下载安装教程(包含JDK安装)【保姆级教学】【2024.4已更新】

目录 文章最后附下载链接 第一步&#xff1a;下载Eclipse&#xff0c;并安装 第二步&#xff1a;下载JDK&#xff0c;并安装 第三步&#xff1a;Java运行环境配置 安装Eclipse必须同时安装JDK &#xff01;&#xff01;&#xff01; 文章最后附下载链接 第一步&#xf…

微软推出的Microsoft Fabric 到底是什么?

近期&#xff0c;总有客户问小编&#xff0c;微软推出的 Microsoft Fabric 是什么&#xff1f;这个产品有什么特别之处呢&#xff1f;希望下面这篇文章能为大家解开一些疑惑。 微软Fabric是2023年5月推出的一个数据分析平台&#xff0c;它将关键数据管理和分析工作负载整合到一…

【设计模式】JAVA Design Patterns——Acyclic Visitor(非循环访问者模式)

&#x1f50d;目的 允许将新功能添加到现有的类层次结构中&#xff0c;而不会影响这些层次结构&#xff0c;也不会有四人帮访客模式中那样循环依赖的问题。 &#x1f50d;解释 真实世界例子 我们有一个调制解调器类的层次结构。 需要使用基于过滤条件的外部算法&#xff08;是…

奖金+1 万,OpenTenBase 开源核心贡献挑战赛,KB 专家助力其跑在 K8s 上

OpenTenBase 是由开放原子开源基金会孵化及运营的开源项目&#xff0c;是一款开放中立的企业级分布式 HTAP 开源数据库。OpenTenBase 具备高扩展性、商业数据库语法兼容、分布式 HTAP 引擎、多级容灾和多维度资源隔离等能力&#xff0c;已成功应用于金融、医疗、航天等行业的核…

FlyFlow:支持驳回后自动跨节点跳回

本周更新 新增&#xff1a;审批节点驳回&#xff08;拒绝配置的驳回&#xff09;支持自动跳回当前节点新增&#xff1a;修改数据节点新增&#xff1a;删除数据节点新增&#xff1a;子流程支持配置自动跳过发起人节点优化&#xff1a;两个项目合并一个单体项目优化&#xff1a;…

【C语言】水仙花数

问题 水仙花数&#xff08;Narcissistic number&#xff09;也被称为超完全数字不变数&#xff08;pluperfect digital invariant, PPDI&#xff09;、自恋数、自幂数或阿姆斯壮数数&#xff08;Armstrong number&#xff09;。 它是指一个n位数&#xff08;n≥3&#xff09;…

【C++】---继承

【C】---继承 一、继承的概念及定义1、继承的概念2、定义语法格式3、继承基类成员访问方式的变化 二、基类 和 派生类 的对象之间的赋值转换1、赋值规则2、切片&#xff08;1&#xff09;子类对象 赋值 给 父类对象&#xff08;2&#xff09;子类对象 赋值 给 父类指针&#xf…

Python邮件处理库之flanker使用详解

概要 Flanker是一个开源的邮件处理库,专门设计用于解析、验证和构建电子邮件地址和MIME消息。由Mailgun开发,它旨在提高邮件处理的效率和准确性,尤其适用于需要高效邮件验证和解析的应用程序。 安装 安装Flanker非常简单,可以通过Python的包管理器pip进行安装: pip ins…

信息流中的混排与流控

待完成. 一. 背景 问题特点: 无法事先拿到所有请求, 离线统一求解. 因此叫 online-matching.应用于在线服务, 求解rt不能高于50ms 二. CIKM 22’, 阿里广告动态定坑 见参考[1]. 2.1 问题建模,动态背包 略, 详见论文 2.2 求解, pidbeam search 思考: beam search 有用的…

使用 cloudflare 免费服务,搭建临时邮箱,无需暴露自己的真实邮箱地址,保护个人隐私

使用 cloudflare 免费服务&#xff0c;搭建临时邮箱 地址 在线演示 &#x1f310;Github地址 https://github.com/find-xposed-magisk/cloudflare_temp_email 功能/TODO Cloudflare D1 作为数据库 使用 Cloudflare Pages 部署前端 使用 Cloudflare Workers 部署后端 email 转…