什么是拓扑排序及其Python实现

文章目录

    • 一,有向无环图
      • 1.1 什么是有向无环图
      • 1.2 有向无环图的应用
      • 1.3 如何表示子工程(活动)
    • 二,拓扑排序
      • 2.1 AOV 网的特点
      • 2.2 拓扑排序
        • 2.2.1 定义与方法
        • 2.2.2 检测 AOV网中是否存在回路
    • 三,Python实现拓扑排序

参考视频: 数据结构与算法基础–第11周09–6.6图的应用9–6.6.3拓扑排序

一,有向无环图

1.1 什么是有向无环图

有向无环图:无环的有向图,简称:DAG图(Directed Acycline Graph)
什么是拓扑排序及其Python实现_第1张图片

1.2 有向无环图的应用

  • 有向无环图常用来描述一个工程或系统的进行过程。(通常把计划、施工、生产、程序流程等当成是一个工程)
  • 一个工程可以分为若干个子工程,只要完成了这些子工程(活动),就可以导致整个工程的完成。

1.3 如何表示子工程(活动)

AOV 网(拓扑排序)

  • 用一个有向图表示一个工程的各子工程及其相互制约的关系,其中以顶点表示活动弧表示活动之间的优先制约关系,称这种有向图为顶点表示活动的网,简称 AOV网(Activity On Vertex network)。

AOE 网(关键路径)

  • 用一个有向图表示一个工程的各子工程及其相互制约的关系,以弧(边)表示活动,以顶点表示活动的开始或结束事件,称这种有向图为边表示活动的网,简称为 AOE网(Activity On Edge)。

二,拓扑排序

拓扑排序引例:排课表

  • 使用定点来表示课程
  • 可以直观的表现出该课程有哪些先修课程
    什么是拓扑排序及其Python实现_第2张图片

2.1 AOV 网的特点

  • 若从 i 到 j 有一条有向路径,则 i 是 j 的前驱;j 是 i 的后继。
  • 若 < i, j > 是网中有向边,则 i 是 j 的直接前驱;j 是 i 的直接后继。
  • AOV 网中不允许有回路,因为如果有回路存在,则表明某项活动以自己为先决条件,显然这是不合理的。

2.2 拓扑排序

2.2.1 定义与方法

定义

  • 在 AOV网没有回路的前提下,我们将全部活动排列成一个线性序列,使得若 AOV网中有弧 < i, j > 存在,则在这个序列中,i 一定排在 j 的前边,具有这种性质的线性序列称为拓扑有序序列,相应的拓扑有序排序的算法称为拓扑排序

拓扑排序的方法

  1. 在有向图中选一个没有前驱的顶点
    什么是拓扑排序及其Python实现_第3张图片
  2. 从图中删除该顶点和所有以它为尾的弧
    什么是拓扑排序及其Python实现_第4张图片
  3. 重复上述两步,直至全部顶点均已输出;或者当图中不存在无前驱的定点为止。

因为每次选择无前驱顶点时都是随机的,所以可能会出现排序结果不同的情况,如下所示。
什么是拓扑排序及其Python实现_第5张图片

2.2.2 检测 AOV网中是否存在回路

检测AOV网中是否存在环的方法:

  • 对有向图构造其顶点的拓扑有序序列,若网中所有的顶点都在它的拓扑有序序列中,则该 AOV网必定不存在环。
  • 例如下图,c3、c6、c8 互为前驱和后继,不可能在拓扑排序中被选中和删除,最终会被留下。
    什么是拓扑排序及其Python实现_第6张图片

三,Python实现拓扑排序

参考:菜鸟教程 - Python 拓扑排序

from collections import defaultdict 
 
class Graph: 
    def __init__(self,vertices): 
        self.graph = defaultdict(list) 
        self.V = vertices
  
    def addEdge(self,u,v): 
        self.graph[u].append(v) 
  
    def topologicalSortUtil(self,v,visited,stack): 
  
        visited[v] = True
  
        for i in self.graph[v]: 
            if visited[i] == False: 
                self.topologicalSortUtil(i,visited,stack) 
  
        stack.insert(0,v) 
  
    def topologicalSort(self): 
        visited = [False]*self.V 
        stack =[] 
  
        for i in range(self.V): 
            if visited[i] == False: 
                self.topologicalSortUtil(i,visited,stack) 
  
        print (stack) 
  
g= Graph(6) 
g.addEdge(5, 2); 
g.addEdge(5, 0); 
g.addEdge(4, 0); 
g.addEdge(4, 1); 
g.addEdge(2, 3); 
g.addEdge(3, 1); 
  
print ("拓扑排序结果:")
g.topologicalSort()
>>>拓扑排序结果:[5, 4, 2, 3, 1, 0]

你可能感兴趣的:(演算法)