算法与数据结构(七) 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可知,可以首先加热平底锅或者混合原材料.我们借助拓扑排序这种图算法来确定制作松饼的步 ...
随机推荐
- AutoMapper
什么是AutoMapper? AutoMapper是一个对象和对象间的映射器.对象与对象的映射是通过转变一种类型的输入对象为一种不同类型的输出对象工作的.让AutoMapper有意思的地方在于它提供了 ...
- KMP算法求解
// KMP.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<iostream> using namespac ...
- Concepts:Request 和 Task
当SQL Server Engine 接收到Session发出的Request时,SQL Server OS将Request和Task绑定,并为Task分配一个Workder.在TSQL Query执 ...
- 【开源】分享2011-2015年全国城市历史天气数据库【Sqlite+C#访问程序】
由于个人研究需要,需要采集天气历史数据,前一篇文章:C#+HtmlAgilityPack+XPath带你采集数据(以采集天气数据为例子),介绍了基本的采集思路和核心代码,经过1个星期的采集,历史数据库 ...
- Android学习路线总结,绝对干货
title: Android学习路线总结,绝对干货 tags: Android学习路线,Android学习资料,怎么学习android grammar_cjkRuby: true --- 一.前言 不 ...
- css3线条围绕跑马+jquery打字机效果
原文地址:css3线条围绕跑马+jquery打字机效果 有图有真相,今天偶然看到了一种效果,仔细看了下,发现它是用css的clip+css3的动画实现的,简直叼.于是自己拿来了前一阵子写的打字机效果, ...
- 代码的坏味道(17)——夸夸其谈未来性(Speculative Generality)
坏味道--夸夸其谈未来性(Speculative Generality) 特征 存在未被使用的类.函数.字段或参数. 问题原因 有时,代码仅仅为了支持未来的特性而产生,然而却一直未实现.结果,代码变得 ...
- Java compiler level does not match解决方法
从别的地方导入一个项目的时候,经常会遇到eclipse/Myeclipse报Description Resource Path Location Type Java compiler level d ...
- stringstream的基本用法
原帖地址:https://zhidao.baidu.com/question/580048330.htmlstringstream是字符串流.它将流与存储在内存中的string对象绑定起来.在多种数据 ...
- OSGi规范的C#实现开源
这是大约在3-4年前完成的一个C#实现的OSGi框架,实现的过程参照了OSGi规范与与一些实现思路(感谢当时的那些资料与项目),此框架虽然仅在几个小型项目有过实际的应用,但OSGi的规范实现还是相对比 ...