今天博客的内容依然与图有关,今天博客的主题是关于拓扑排序的。拓扑排序是基于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可知,可以首先加热平底锅或者混合原材料.我们借助拓扑排序这种图算法来确定制作松饼的步 ...
随机推荐
-
GERBER文件
GERBER文件 GERBER文件是一种国际标准的光绘格式文件,它包含RS-274-D和RS-274-X两种格式,其中RS-274-D称为基本GERBER格式,并 要同时附带D码文件才能完整描述一张图 ...
-
.net web 点击链接在页面指定位置显示DIV的问题
做了一个网页,放了两个DataList ,一个显示科室,一个显示科室中的人员,由于科室太多,一屏显示不全,为了在页面刷新时记住上次浏览位置,所以给页面加了MaintainScrollPositionO ...
-
JS 时间与时间戳的相互转换
<script type="text/javascript"> var time = "2015-04-22 21:41:43";//2015-4- ...
-
ArcGis : unable to save as template this document is already based on another template
原文:http://forums.esri.com/Thread.asp?c=93&f=989&t=289930 ----------------- I ran into this p ...
-
velocity序列动画
结合上次提到的velocity的UI Pack存在一下问题: 动画名称过长,语意性差 使用UI Pack的动画,loop属性会失效 无法监听动画完成时机 我这里想到了一种解决 ...
-
hnnu 11546 Sum of f(x) (求一个数的全部约数和)
代码: #include<cstdio> #include<cstring> #define N 200000 using namespace std; long long f ...
-
解决phpmyadmin 点击表结构时卡顿、一直加载、打不开的问题
本文内容是转自其它站点,亲测可用. 第一步,打开 ./version_check.php文件,找到以下代码: $save = true; $file ='http://www.phpmyadmin.n ...
-
ECharts, PHP, MySQL, Ajax, JQuery 实现前后端数据可视化
ECharts 下载js代码 工作原理浅析 在项目中引入ECharts 后台处理 数据库端MySQL PHP端 JQuery Ajax处理 ECharts 端处理 前端全部代码 演示结果 总结 最近要 ...
-
【Vue】---编写Vue插件流程---【巷子】
一.在Vue中编写插件流程 1.创建组件 components/message.vue <template> <div class="message" v-if= ...
-
Centos 5.2 下配置 php 的 json 扩展
01.下载源文件包: wget http://www.aurore.net/projects/php-json/php-json-ext-1.2.1.tar.bz2 02.解压文件包: tar ...