什麼是拓撲排序及其Python實現


參考視頻:數據結構與算法基礎–第11周09–6.6圖的應用9–6.6.3拓撲排序

一,有向無環圖

1.1 什麼是有向無環圖

有向無環圖:無環的有向圖,簡稱:DAG圖(Directed Acycline Graph)
在這裏插入圖片描述

1.2 有向無環圖的應用

  • 有向無環圖常用來描述一個工程或系統的進行過程。(通常把計劃、施工、生產、程序流程等當成是一個工程)
  • 一個工程可以分爲若干個子工程,只要完成了這些子工程(活動),就可以導致整個工程的完成。

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

AOV 網(拓撲排序)

  • 用一個有向圖表示一個工程的各子工程及其相互制約的關係,其中以頂點表示活動弧表示活動之間的優先制約關係,稱這種有向圖爲頂點表示活動的網,簡稱 AOV網(Activity On Vertex network)。

AOE 網(關鍵路徑)

  • 用一個有向圖表示一個工程的各子工程及其相互制約的關係,以弧(邊)表示活動,以頂點表示活動的開始或結束事件,稱這種有向圖爲邊表示活動的網,簡稱爲 AOE網(Activity On Edge)。

二,拓撲排序

拓撲排序引例:排課表

  • 使用定點來表示課程
  • 可以直觀的表現出該課程有哪些先修課程
    在這裏插入圖片描述

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. 在有向圖中選一個沒有前驅的頂點
    在這裏插入圖片描述
  2. 從圖中刪除該頂點和所有以它爲尾的弧
    在這裏插入圖片描述
  3. 重複上述兩步,直至全部頂點均已輸出;或者當圖中不存在無前驅的定點爲止。

因爲每次選擇無前驅頂點時都是隨機的,所以可能會出現排序結果不同的情況,如下所示。
在這裏插入圖片描述

2.2.2 檢測 AOV網中是否存在迴路

檢測AOV網中是否存在環的方法:

  • 對有向圖構造其頂點的拓撲有序序列,若網中所有的頂點都在它的拓撲有序序列中,則該 AOV網必定不存在環。
  • 例如下圖,c3、c6、c8 互爲前驅和後繼,不可能在拓撲排序中被選中和刪除,最終會被留下。
    在這裏插入圖片描述

三,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]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章