算法与数据结构(七) AOV网的拓扑排序
今天博客的内容依然与图有关,今天博客的主题是关于拓扑排序的。拓扑排序是基于AOV网的,关于AOV网的概念,我想引用下方这句话来介绍:
AOV网:在现代化管理中,人们常用有向图来描述和分析一项工程的计划和实施过程,一个工程常被分为多个小的子工程,这些子工程被称为活动(Activity),在有向图中若以顶点表示活动,有向边表示活动之间的先后关系,这样的图简称为AOV网。
说的简单点,AOV网就是表示一个工程中某些子项的先后顺序。就拿工地搬砖来说吧,只有砖厂送来砖,工人才能搬。那么砖厂送砖就是搬砖的前提。先这么一聊,下方会给出详细的介绍。废话少说进入今天的主题。
一、AOV网与拓扑排序
本篇博客我们先聊一下AOV网和拓扑排序的关系,下方是我们列举的一个非常简单的例子,当然下方的这个图就是一个简单的AOV图,麻雀虽小,五脏俱全。在下方的AOV图中,送砖和找人是并列的,先执行谁都行。不过搬砖的前提是即送完了砖也找完了人,然后就可以开始搬砖了,所以送砖和找人就是搬砖的前提。那么让搬砖这件事情顺利进行下去的顺序有"送砖->找人->搬砖"或者“找人->送砖->搬砖”这两个序列,而这两个序列都是拓扑序列。
生成“送砖->找人->搬砖”这个序列的过程我们称之为拓扑排序。如果非得说的官方和抽象点,那么还是引用拓扑排序的定义吧,下方就是拓扑排序的定义:
拓扑排序:对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在v之前。通常,这样的线性序列称为满足拓扑次序(Topological Order)的序列,简称拓扑序列。简单的说,由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序。
上面这个定义就比较抽象了,当然还是我们搬砖的例子好理解一些。在有向无环图中的结点如果有入度的话,那么就说明该结点优先级要低于那些可以到达改点的结点。而那些没有入度的结点的优先级就比较高,这些结点的完成不依赖与其他结点。这样说如果有些抽象的话,那么我们就看下方拓扑排序详细的示例图。
二、拓扑排序示意图
本部分我们将会给出拓扑排序详细的示意图。拓扑排序实现是依赖于栈与队列的数据结构,栈用来暂存那些入度为0的结点,而队列负责存储已经生成的拓扑序列。因为前几篇关于图的博客,我们都使用了相同的图结构。本篇博客也不例外,我们依然会使用之前的有向图,因为之前的图是有向无环图,所以是可以生成拓扑序列的。下方就是要生成拓扑序列的有向无环图。
在下方的有向无环图每个结点上有一个绿色的数字,该数字记录的就是该结点的入度。入度为零,那么该数字就是0,如果入度为1,那么该数字就是1。
下方是下图拓扑排序每一步的示意图。接下来我们将会给出下方每一步示意图的详细解说。
(1):首先将图中入度为0的结点入栈,因为此图中只有A结点的入度为0,所以我们将A入栈。
(2):将A从栈中Pop到我们的拓扑队列中,将那些以A发出的边为入度的结点的度数减一。对于此示例来说也就是将B和F入度减1. 因为B和F的入度数减一后成了0,所以也将B, F这两结点入栈。
(3):将F从栈中Pop到拓扑队列中,因为图中有F->G和F->E两条边,所以将G和E的入度数减一。因为E的入度数减一后为0,所以将E入栈。
(4):将E从栈中Pop到拓扑队列中,因为图中E->H和E->D两条边,所以讲H和D的两个结点的入度减一。两个结点减一操作后没有入度为零的节点,所以本步没有结点入栈。
(5):接着从栈中Pop结点到拓扑队列中,将B结点Pop出栈入拓扑队列。因为C、I、G结点与B相连,B添加进拓扑序列后,这三个结点的入度都减一。C和G的入度减一后为0,所以将其加入栈中。
(6):将C从栈中pop到拓扑队列中,与C相连的结点是I和D, 将这两个结点的入度减1。I的入度减一后为0,将其Push到栈中暂存。
(7):将I结点从栈中pop到拓扑队列中,D与I相连,将D的入度再次减一。本轮没有要入栈的结点。
(8):将G从栈中pop到拓扑队列中,G与H和D相连,将D与H的入度减一。H的入度减一操作后入度为零将其入栈。
(9):将H从站中pop到拓扑队列中,D与H相连,将D的入度减一,减一后为0,所以将D入栈。
(10):将D从栈中pop到拓扑队列中,此刻栈中为空,拓扑序列生成完毕。
上面这些步骤已经很详细了,上面这些步骤搞明白后,给出代码实现就简单多了。下方我们会给出具体的代码实现。
三、拓扑排序的代码实现
讲完概念和原理后,接下来我们就要开始实践了。本部分就会给出具体的代码实现,当然我们依然采用Swift语言来做。首先我们创建要依赖的队列和栈,然后再构建有向图的邻接链表,最后给出拓扑排序的代码实现。进入本部分的主题:
1.队列与栈
接下来我们就要实现拓扑序列生成时要使用的栈与队列,关于栈与队列本篇博客就不做过多的赘述了,因为我们之前已经对栈与队列做了详细的介绍。关于栈与队列更详细的内容请查看之前的博客《栈与队列的线性和链式表示(Swift面向对象版)》。
下方这段代码段就是我们本篇博客要使用的栈的类,当然是简化版的,也就是对Array做了一个简单的封装。栈中存储的数据类型是我们邻接链表的结点。具体代码如下所示。
下方则是我们存储拓扑序列的队列,当然也是基于Array的简单封装。
2.有向图的构建
接下来我们来创建我们的有向图。本篇博客所使用的有向图我们是使用邻接链表来表示的。下方这段代码段就是邻接链表的结点,当然在之前不知一篇博客中我们使用到了下方这个结点。本篇博客中的weightNumber不仅仅只存边的权值,在数组中的结点的weightNumber我们用来存储该结点的入度。
下方这段代码就是有向图的创建,在网邻接链表上挂入结点时,要讲被挂入的结点的入度加1即可。因为下方代码与之前图的创建的代码类似,在此就不做过多赘述了。
下方这两个截图则是上述代码段的输入和输出。根据输出的结果我们不难看出我们所创建的图就是一个有向图。
3、拓扑序列的生成
接下来就是我们本篇博客代码实现的核心了。我们将基于上面创建的AOV网来生成拓扑序列。其实下方生成拓扑序列的代码就是上述示例描述的具体实现。接下来我们将具体的说下下方这段拓扑排序的代码。主要概括起来分为下方三步:
(1):首先初始化我们所需要的栈,然后遍历AOV网中所有的结点,将入度为0的结点添加到我们的栈中暂存。
(2):循环将我们栈中的元素添加到拓扑队列中。每从栈中Pop出一个结点就把与该结点相连的结点的入度减1,如果减一后该结点的度数为0则将其入栈。然后继续下一轮的循环。
(3):当栈中没有暂存的结点后,说明拓扑序列生成完毕。如果拓扑队列中的元素要小于图结点的个数,那么说明图中存在环路,不能生成相应的拓扑序列。
下方截图就是我们之前创建的有向图所生成的拓扑序列,如下所示:
至此,我们本篇博客的内容也就结束了,下方依然是我们本篇博客所涉及Demo的分享链接,如下所示:
github分享链接:https://github.com/lizelu/DataStruct-Swift/tree/master/TopoLogicalSort
算法与数据结构(七) AOV网的拓扑排序的更多相关文章
- 算法与数据结构(七) AOV网的拓扑排序(Swift版)
今天博客的内容依然与图有关,今天博客的主题是关于拓扑排序的.拓扑排序是基于AOV网的,关于AOV网的概念,我想引用下方这句话来介绍: AOV网:在现代化管理中,人们常用有向图来描述和分析一项工程的计划 ...
- 算法与数据结构(八) AOV网的关键路径
上篇博客我们介绍了AOV网的拓扑序列,请参考<数据结构(七) AOV网的拓扑排序(Swift面向对象版)>.拓扑序列中包括项目的每个结点,沿着拓扑序列将项目进行下去是肯定可以将项目完成的, ...
- 算法与数据结构(八) AOV网的关键路径(Swift版)
上篇博客我们介绍了AOV网的拓扑序列,请参考<数据结构(七) AOV网的拓扑排序(Swift面向对象版)>.拓扑序列中包括项目的每个结点,沿着拓扑序列将项目进行下去是肯定可以将项目完成的, ...
- AOV网与拓扑排序
在一个表示工程的有向图中,用顶点表示活动,用弧表示活动之间的优先关系,这样的有向图为顶点表示活动的网,我们称之为AOV网(Activity on Vextex Network).AOV网中的弧表示活动 ...
- 有向无环图的应用—AOV网 和 拓扑排序
有向无环图:无环的有向图,简称 DAG (Directed Acycline Graph) 图. 一个有向图的生成树是一个有向树,一个非连通有向图的若干强连通分量生成若干有向树,这些有向数形成生成森林 ...
- AOV图与拓扑排序&AOE图与关键路径
AOV网:所有的工程或者某种流程可以分为若干个小的工程或阶段,这些小的工程或阶段就称为活动.若以图中的顶点来表示活动,有向边表示活动之间的优先关系,则这样活动在顶点上的有向图称为AOV网. 拓扑排序算 ...
- 浅谈算法和数据结构: 七 二叉查找树 八 平衡查找树之2-3树 九 平衡查找树之红黑树 十 平衡查找树之B树
http://www.cnblogs.com/yangecnu/p/Introduce-Binary-Search-Tree.html 前文介绍了符号表的两种实现,无序链表和有序数组,无序链表在插入的 ...
- 数据结构之---C语言实现拓扑排序AOV图
//有向图的拓扑排序 //杨鑫 #include <stdio.h> #include <stdlib.h> #include <string.h> #define ...
- 【数据结构与算法Python版学习笔记】图——拓扑排序 Topological Sort
概念 很多问题都可转化为图, 利用图算法解决 例如早餐吃薄煎饼的过程 制作松饼的难点在于知道先做哪一步.从图7-18可知,可以首先加热平底锅或者混合原材料.我们借助拓扑排序这种图算法来确定制作松饼的步 ...
随机推荐
- Storm如何保证可靠的消息处理
作者:Jack47 PS:如果喜欢我写的文章,欢迎关注我的微信公众账号程序员杰克,两边的文章会同步,也可以添加我的RSS订阅源. 本文主要翻译自Storm官方文档Guaranteeing messag ...
- C# 注册 Windows 热键
闲扯: 前几日,一个朋友问我如何实现按 F1 键实现粘贴(Ctrl+V)功能,百度了一个方法,发给他,他看不懂(已经是 Boss 的曾经的码农),我就做了个Demo给他参考.今日得空,将 Demo 整 ...
- angular实现统一的消息服务
后台API返回的消息怎么显示更优雅,怎么处理才更简洁?看看这个效果怎么样? 自定义指令和服务实现 自定义指令和服务实现消息自动显示在页面的顶部,3秒之后消失 1. 显示消息 这种显示消息的方式是不是有 ...
- 23种设计模式--观察者模式-Observer Pattern
一.观察者模式的介绍 观察者模式从字面的意思上理解,肯定有两个对象一个是观察者,另外一个是被观察者,观察者模式就是当被观察者发生改变得时候发送通知给观察者,当然这个观察者可以是多个对象,在项 ...
- PHP中遍历XML之SimpleXML
简单来讲述一些XML吧,XML是可扩展标记语言,是一种用于标记电子文件使其具有结构性的标记语言.XML是当今用于传输数据的两大工具之一,另外一个是json. 我们在PHP中使用XML也是用来传输数据, ...
- JavaScript中事件处理
先看看下面一道题目,请评价以下代码并给出改进意见: if (window.addEventListener) {//标准浏览器 var addListener = function(el, type, ...
- obj.style.z-index的正确写法
obj.style.z-index的正确写法 今天发现obj.style.z-index在js里面报错,后来才知道在js里应该把含"-"的字符写成驼峰式,例如obj.style.z ...
- VS项目中使用Nuget还原包后编译生产还一直报错?
Nuget官网下载Nuget项目包的命令地址:https://www.nuget.org/packages 今天就遇到一个比较奇葩的问题,折腾了很久终于搞定了: 问题是这样的:我的解决方案原本是好好的 ...
- mongodb
修改所有的记录: > db.t_express_apply.update({},{$set:{"isStatus" : 0}},{multi:true})WriteResul ...
- 微软开源代码编辑器monaco-editor
官网上给出:”The Monaco Editor is the code editor that powers VS Code. A good page describing the code edi ...