图搜索算法 - 拓扑排序

相关文章:
数据结构–图的概念
图搜索算法 - 深度优先搜索法(DFS)
图搜索算法 - 广度优先搜索法(BFS)

拓扑排序

概念

几乎所有的工程都可分为若干个称作活动的子工程,而这些子工程之间,通常受着一定条件的约束,如其中某些子工程的开始必须在另一些子工程完成之后。对整个工程和系统,人们关心的是两个方面的问题:一是工程能否顺利进行;二是估算整个工程完成所必须的最短时间。这样两个问题都是可以通过对有向图进行拓扑排序和关键路径操作来解决的。当然这里说的工程,泛指一切的项目工程,如指令调度,数据序列化,软件安装包依赖关系,代码编译任务顺序等。

拓扑排序是对项目工程的排序,那么先来构建一个项目,比如这个项目制作番茄炒蛋,如图所示。
在这里插入图片描述
对一个有向无环图G进行拓扑排序,是将G中所有结点排成一个线性序列,使得图中任意一对结点u和v,u在线性序列中总是出现在v之前。如上面做菜顺序0-1-2-3-4-5-9-6-7-8,也可以0-3-2-1-4-5-9-6-7-8这样,都满足拓扑次序(Topological Order),也就是番茄总是要洗了再切,番茄要切成小块再炒,不能整个炒,这样的顺序不会改变,这简称拓扑序列。简单的说,由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序。

注意:偏序是指集合中仅有部分元素可比较大小(或先后),全序是指集合中所有元素可比较大小(或先后)。

原理

拓扑排序算法是基于深度优先搜索(以下简称DFS)的基础上做调整的,首先查看例子用DFS计算是怎样的结果,从结点【1】开始继续搜索,结果是0-1-4-7-8-2-5-9-3-6。显然这是不是拓扑排序的结果,因此要略为修改DFS。从一个结点出发,DFS是马上输出再递归进入相邻结点,这是不适合拓扑排序。这里应该先访问相邻的结点,若还有相邻结点,继续深入下一个结点,当所有相邻的结点都进入栈后,才把该结点推入栈,以下手动模拟此运算过程。

(1)首先初始化列表【visited】全部为【False】,所有结点刚开始都是未访问以及临时栈【stack】为空。然后从结点【0】开始,然后发现有3个结点,然后继续访问结点【1】,同理一直深入访问结点【4】、结点【7】和结点【8】,到这里没有发现相邻结点,那边我们把结点【8】入栈,然后回退到结点【7】,同样它也没有其他相邻结点,同样也入栈,同理结点【4】和结点【1】也一起入栈,如表所示。
在这里插入图片描述
(2)回到结点【0】,发现还有相邻结点【2】和【3】,然后我们访问结点【2】,同样一层层深入结点,直到结点【8】,由于它已经访问过了,所以不需要再次放到栈里面。然后回退到上一个结点【9】就可以放到栈里面,同理结点【5】和【2】也一起入栈,如表所示。
在这里插入图片描述
(3)继续访问未访问结点【3】,然后进入结点【6】,然后再想进一步访问结点【7】,发现它也在栈中,所以可以停止递归,把结点【6】推入栈,再把结点【3】入栈,这时候结点【0】所有相邻结点也访问完,也可以把它入栈,如表所示。
在这里插入图片描述
(4)这时候从栈中输出结果,从顶部结点开始结构为0-3-6-2-5-9-1-4-7-8,符合了拓扑排序的要求。
在编写代码前,先来分析算法的复杂度,如果图中有N个结点,E条边,在拓扑排序的过程中,因为复用【Graph】类,则使用邻接列表来表示图,所以查找所有结点的邻接结点所需时间为O(N),访问结点的邻接点所花时间为O(E),总的时间复杂度为O(N+E)。空间复杂度为递归深度,极限情况就是结点总数,则为O(N)。

class Graph(): """图类"""def __init__(self): self.graph = {}  # 初始化图的邻接列表def add_edge(self,u,v): if v:point = self.graph.get(u) # 尝试获取结点uif point:point.append(v)       # 若存在直接添加u-v的边else:self.graph[u] = [v]   # 若不存在,则先初始化u结点,然后再添加u-v的边else:self.graph[u] = list()  # 如果v没有值,添加一个空列表class GraphTopological(Graph):"""解决拓扑排序问题"""def topological_sort_util(self, v, visited, stack): visited[v] = True       # 该结点变为已访问for i in self.graph[v]: if visited[i] == False: # 结点未访问递归调用函数self.topological_sort_util(i, visited, stack) # 相邻结点都访问结束后,把该结点放到栈中stack.insert(0,v)  # 把新入栈元素放在表头def topological_sort(self):# 拓扑排序主程序visited = {}   # 初始化参数是否已经访问stack = [] # 初始化参数,用列表表示临时栈为空for key in self.graph.keys():visited[key] = False     # 值为未访问状态for node in self.graph.keys(): # 遍历所有结点 if visited[node] == False: # 结点是否已经访问self.topological_sort_util(node, visited, stack) # 递归进入结点print(stack) #把栈保存结果输出

创建【TopologicalGraph】类继承上面【Graph】类,复用构成邻接列表的过程。然后用列表构成栈,把递归结果保存在列表中,最后从栈表头开始输出结果便是拓扑排序的结果,现在用例子来测试结果是否符合预期。

g = GraphTopological() 
g.add_edge(0, 1) # 录入图的边
g.add_edge(0, 2) 
g.add_edge(0, 3) 
g.add_edge(1, 4) 
g.add_edge(2, 5) 
g.add_edge(3, 6)
g.add_edge(4, 7)
g.add_edge(5, 9)
g.add_edge(6, 7)
g.add_edge(7, 8)
g.add_edge(8, None)
g.add_edge(9, 8)
g.topological_sort() # 输出:[0, 3, 6, 2, 5, 9, 1, 4, 7, 8]

结果和刚才手动计算是一样,如果调换输入顺序,把第二行放到第四行,拓扑排序的结果如下。

[0, 1, 4, 3, 6, 7, 2, 5, 9, 8]

结果只是改变了遍历结点【1】,【2】和【3】的顺序,结果还是满足拓扑次序。

更多内容

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

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

Debug项目失败Run成功

一:问题 idea中启动服务,服务一直在启动中,最后超时启动失败 重新构建项目也是一样 二:个人分析 debug因为断点太多了项目起不起来,试一下run直接运行,项目可以快速启动 三:解决办法 在控制…

四、Redis五种常用数据类型-List

List是Redis中的列表,按照插入顺序保存数据,插入顺序是什么样的,数据就怎么保存。可以添加一个元素到列表的头部(左边)或者尾部(右边)。一个列表最多可以包含232-1个元素(4294967295,每个列表超过40亿个元素)。是一种双向列表结构…

uniapp 如何修改 IPA 文件信息页的本地化语言

实现效果: 最终会对应到苹果商店的语言: 例如微信的语言就有多个: 操作: 在 mainfest.json 源码视图中加入: 具体对应的语言key值可以参考Xcode中的语言代码 这个取决于打包后的 lproj 文件 将后缀ipa改成zip打开即…

47. UE5 RPG 实现角色死亡效果

在上一篇文章中,我们实现了敌人受到攻击后会播放受击动画,并且还给角色设置了受击标签。并在角色受击时,在角色身上挂上受击标签,在c里,如果挂载了此标签,速度将降为0 。 受击有了,接下来我们将…

Linux中gitlab-runner部署使用备忘

环境: 操作系统::CentOS8 gitlab版本:13.11.4 查看gitlab-runner版本 可以从https://packages.gitlab.com/app/runner/gitlab-runner/search找到与安装的gitlab版本相近的gitlab-runner版本以及安装命令等信息,我找到与13.11.4相…

C语言,实现数字谱到简谱的转换(二)

C语言,实现数字谱到简谱的转换(二) 前言:本文初编辑于2024年5月8日 CSDN:https://blog.csdn.net/rvdgdsva 博客园:https://www.cnblogs.com/hassle 前言 结合前文使用 之前的程序默认C调4/4拍&#xff…

windows11获取笔记本电脑电池健康报告

笔记本电脑的电池关系到我们外出时使用的安全,如果电池健康有问题需要及时更换,windows系统提供了检查电池健康度的方法。 1、打开命令行 1)键入 winR 2)键入 cmd 打开命令行。 2、在命令行运行如下指令,生成电池健…

美式期权和欧式期权区别的详细解析

美式期权和欧式期权的区别 美式期权和欧式期权是期权交易的两种主要形式,它们主要在行权时间、灵活性和价格等方面存在显著的区别。 文章来源/:股指研究院 美式期权的特点在于其买方可以在期权有效期内任何一天提出执行合约,即买方可以在到…

人工智能哪些大学比较好

人工智能领域的大学有很多,以下是一些国际上被广泛认可的一流大学: 1. **斯坦福大学(Stanford University)** - 位于美国加州的斯坦福大学拥有顶尖的人工智能研究中心,并在机器学习、自然语言处理等领域处于领先地位。…

怿星科技CEO潘凯:汽车软件研发工具链 国产玩家迎「历史性机会」

「智能汽车时代,国内非常有机会出现类似Vector的企业。」 这是怿星科技CEO潘凯深信的事情,他在行业内已经深耕约18年,创业也已经10年有余,带领着一个约300人的公司,2024年4月与高工智能汽车见面时,正值公司…

pdf2htmlEX:pdf 转 html,医学指南精细化处理

pdf2htmlEX:pdf 转 html,医学指南精细化处理 单文件转换多文件转换 代码:https://github.com/coolwanglu/pdf2htmlEX 拉取pdf2htmlEX 的 Docker: docker pull bwits/pdf2htmlex # 拉取 bwits/pdf2htmlex不用进入容器&#xff0c…

初学C++——C++基础、变量、字面量、常量、数据类型、类型转换、变量命名规则、开发环境配置

文章目录 简介C 语言的特性C 开发环境配置C 变量,字面量和常量C 变量变量命名规则 C 字面量C 常量 C 数据类型C 基本数据类型派生数据类型 C 类型转换隐式类型转换C 显式转换 简介 C 是一种静态类型的,自由形式的(通常)编译的&…

一文详解Spring与JDK注入

目录 一、Spring框架 二、JDK 三、什么是Spring的注入 四、如何实现Spring与JDK注入 一、Spring框架 Spring框架是一个开源的Java EE应用程序框架,它为企业级Java应用程序提供了全面的基础设施支持。Spring框架的核心特点包括依赖注入(Dependency I…

存储大作战:探索Local Storage与Session Storage的奥秘

欢迎来到我的博客,代码的世界里,每一行都是一个故事 存储大作战:探索Local Storage与Session Storage的奥秘 前言Local Storage与Session Storage简介数据存储生命周期容量限制安全性 前言 在Web的世界里,数据就像是一群流浪者&a…

如何利用AI提高内容生产效率

目录 一、自动化内容生成 二、内容分发与推广 三、内容分析与优化 图片来源网络,侵权联系可删 一、自动化内容生成 随着AI技术的飞速发展,自动化内容生成已经成为提高内容生产效率的重要手段。AI可以通过自然语言处理(NLP)、机…

vue2 14个指令详解,v-bind操作style,v-bind操作class,以及v-bind动态绑定图片地址不生效的问题

文章目录 vue常用指令内容渲染指令v-textv-html 条件渲染指令v-showv-ifv-else、v-else-iftemplate标签 事件绑定指令v-on事件处理函数传参事件处理函数的事件对象 属性绑定指令v-bind 双向绑定指令v-modelv-model的双向绑定实现原理用在表单元素上用在组件实现父子数据双向绑定…

游戏全自动打金搬砖,单号收益300+ 轻松日入1000+

详情介绍 游戏全自动打金搬砖,单号收益300左右,多开收益更多,轻松日入1000 可矩阵操作。 项目长期稳定,全自动挂机无需人工操作,小白,宝妈,想做副业的都可以。

MouseBoost PRO mac中文激活版:专业鼠标助手

MouseBoost PRO mac鼠标性能优化软件,以其强大的功能和智能化的操作,助您轻松驾驭鼠标,提高工作效率。 MouseBoost PRO支持自定义快捷键设置,让您轻松实现快速切换应用程序、打开特定文件、调节音量大小等操作。自动识别窗口功能则…

Java 8特性(一) 之 手写Stream流filter、map和forEach方法

Java 8特性(一) 之 手写Stream流filter、map和forEach方法 今天看了一下Java 8的Stream流,学习了一下函数式编程,这才感受函数式编程如此爽,之前就使用过ES8.7.1的函数式编程,当时就在想啥时候咱也能写出这…

手拿滑块撕瑞数 我叫超弟你记住!!什么腾讯滑块、数美、阿里通通拿下!最新版2024.5.8号

本文章非标题党,可提供主流验证码解决方案及成品、补环境框架、逆向教学 不论你是逆向小白、亦或是需求方都可通过本文章各取所需!! 废话不多说,老规矩,附上腾讯旗下验证码程序运行图,附程序运行时间 &…