在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
今天博客的内容依然与图有关,今天博客的主题是关于拓扑排序的。拓扑排序是基于AOV网的,关于AOV网的概念,我想引用下方这句话来介绍:
说的简单点,AOV网就是表示一个工程中某些子项的先后顺序。就拿工地搬砖来说吧,只有砖厂送来砖,工人才能搬。那么砖厂送砖就是搬砖的前提。先这么一聊,下方会给出详细的介绍。废话少说进入今天的主题。
一、AOV网与拓扑排序 本篇博客我们先聊一下AOV网和拓扑排序的关系,下方是我们列举的一个非常简单的例子,当然下方的这个图就是一个简单的AOV图,麻雀虽小,五脏俱全。在下方的AOV图中,送砖和找人是并列的,先执行谁都行。不过搬砖的前提是即送完了砖也找完了人,然后就可以开始搬砖了,所以送砖和找人就是搬砖的前提。那么让搬砖这件事情顺利进行下去的顺序有"送砖->找人->搬砖"或者“找人->送砖->搬砖”这两个序列,而这两个序列都是拓扑序列。
生成“送砖->找人->搬砖”这个序列的过程我们称之为拓扑排序。如果非得说的官方和抽象点,那么还是引用拓扑排序的定义吧,下方就是拓扑排序的定义:
上面这个定义就比较抽象了,当然还是我们搬砖的例子好理解一些。在有向无环图中的结点如果有入度的话,那么就说明该结点优先级要低于那些可以到达改点的结点。而那些没有入度的结点的优先级就比较高,这些结点的完成不依赖与其他结点。这样说如果有些抽象的话,那么我们就看下方拓扑排序详细的示例图。
二、拓扑排序示意图 本部分我们将会给出拓扑排序详细的示意图。拓扑排序实现是依赖于栈与队列的数据结构,栈用来暂存那些入度为0的结点,而队列负责存储已经生成的拓扑序列。因为前几篇关于图的博客,我们都使用了相同的图结构。本篇博客也不例外,我们依然会使用之前的有向图,因为之前的图是有向无环图,所以是可以生成拓扑序列的。下方就是要生成拓扑序列的有向无环图。 在下方的有向无环图每个结点上有一个绿色的数字,该数字记录的就是该结点的入度。入度为零,那么该数字就是0,如果入度为1,那么该数字就是1。
下方是下图拓扑排序每一步的示意图。接下来我们将会给出下方每一步示意图的详细解说。
上面这些步骤已经很详细了,上面这些步骤搞明白后,给出代码实现就简单多了。下方我们会给出具体的代码实现。
三、拓扑排序的代码实现 讲完概念和原理后,接下来我们就要开始实践了。本部分就会给出具体的代码实现,当然我们依然采用Swift语言来做。首先我们创建要依赖的队列和栈,然后再构建有向图的邻接链表,最后给出拓扑排序的代码实现。进入本部分的主题:
1.队列与栈 接下来我们就要实现拓扑序列生成时要使用的栈与队列,关于栈与队列本篇博客就不做过多的赘述了,因为我们之前已经对栈与队列做了详细的介绍。关于栈与队列更详细的内容请查看之前的博客《栈与队列的线性和链式表示(Swift面向对象版)》。 下方这段代码段就是我们本篇博客要使用的栈的类,当然是简化版的,也就是对Array做了一个简单的封装。栈中存储的数据类型是我们邻接链表的结点。具体代码如下所示。
下方则是我们存储拓扑序列的队列,当然也是基于Array的简单封装。
2.有向图的构建 接下来我们来创建我们的有向图。本篇博客所使用的有向图我们是使用邻接链表来表示的。下方这段代码段就是邻接链表的结点,当然在之前不知一篇博客中我们使用到了下方这个结点。本篇博客中的weightNumber不仅仅只存边的权值,在数组中的结点的weightNumber我们用来存储该结点的入度。
下方这段代码就是有向图的创建,在网邻接链表上挂入结点时,要讲被挂入的结点的入度加1即可。因为下方代码与之前图的创建的代码类似,在此就不做过多赘述了。
下方这两个截图则是上述代码段的输入和输出。根据输出的结果我们不难看出我们所创建的图就是一个有向图。
3、拓扑序列的生成 接下来就是我们本篇博客代码实现的核心了。我们将基于上面创建的AOV网来生成拓扑序列。其实下方生成拓扑序列的代码就是上述示例描述的具体实现。接下来我们将具体的说下下方这段拓扑排序的代码。主要概括起来分为下方三步:
下方截图就是我们之前创建的有向图所生成的拓扑序列,如下所示:
至此,我们本篇博客的内容也就结束了,下方依然是我们本篇博客所涉及Demo的分享链接,如下所示: github分享链接:https://github.com/lizelu/DataStruct-Swift/tree/master/TopoLogicalSort
|
请发表评论