簡單易懂的拓撲排序

1.定義算法

對一個有向無環圖(Directed Acyclic Graph簡稱DAG) G進行拓撲排序,是將G中全部頂點排成一個線性序列,使得圖中任意一對頂點u和v,若邊(u,v)∈E(G),則u在線性序列中出如今v以前。一般,這樣的線性序列稱爲知足拓撲次序(Topological Order)的序列,簡稱拓撲序列。簡單的說,由某個集合上的一個偏序獲得該集合上的一個全序,這個操做稱之爲拓撲排序。學習

在AOV網中,若不存在迴路,則全部活動可排列成一個線性序列,使得每一個活動的全部前驅活動都排在該活動的前面,咱們把此序列叫作拓撲序列(Topological order),由AOV網構造拓撲序列的過程叫作拓撲排序(Topological sort)。AOV網的拓撲序列不是惟一的,知足上述定義的任一線性序列都稱做它的拓撲序列。 ui

2.拓撲排序的實現步驟spa

在有向圖中選一個沒有前驅的頂點而且輸出。3d

從圖中刪除該頂點和全部以它爲尾的弧(白話就是:刪除全部和它有關的邊)。code

重複上述兩步,直至全部頂點輸出,或者當前圖中不存在無前驅的頂點爲止,後者表明咱們的有向圖是有環的,所以,也能夠經過拓撲排序來判斷一個圖是否有環。blog

3.拓撲排序實例手動實現排序

若是咱們有以下的一個有向無環圖,咱們須要對這個圖的頂點進行拓撲排序,過程以下:隊列

 

首先,咱們發現V6和v1是沒有前驅的,因此咱們就隨機選去一個輸出,咱們先輸出V6,刪除和V6有關的邊,獲得以下圖結果:it

 

而後,咱們繼續尋找沒有前驅的頂點,發現V1沒有前驅,因此輸出V1,刪除和V1有關的邊,獲得下圖的結果:

 

而後,咱們又發現V4和V3都是沒有前驅的,那麼咱們就隨機選取一個頂點輸出(具體看你實現的算法和圖存儲結構),咱們輸出V4,獲得以下圖結果:

 

而後,咱們輸出沒有前驅的頂點V3,獲得以下結果:

 

而後,咱們分別輸出V5和V2,最後所有頂點輸出完成,該圖的一個拓撲序列爲:

v6–>v1—->v4—>v3—>v5—>v2

過程簡述:

從 DAG 圖中選擇一個 沒有前驅(即入度爲0)的頂點並輸出。

從圖中刪除該頂點和全部以它爲起點的有向邊。

重複 1 和 2 直到當前的 DAG 圖爲空或當前圖中不存在無前驅的頂點爲止。若當前圖中不存在無前驅的頂點說明有向圖中必存在環。

4.拓撲排序Java實現

(1)   示例

如今你總共有 n 門課須要選,記爲 0 到 n-1。

在選修某些課程以前須要一些先修課程。 例如,想要學習課程 0 ,你須要先完成課程 1 ,咱們用一個匹配來表示他們: [0,1]

給定課程總量以及它們的先決條件,判斷是否可能完成全部課程的學習?

示例 1:

輸入: 2, [[1,0]]

輸出: true

解釋: 總共有 2 門課程。學習課程 1 以前,你須要完成課程 0。因此這是可能的。

示例 2:

輸入: 2, [[1,0],[0,1]]

輸出: false

解釋: 總共有 2 門課程。學習課程 1 以前,你須要先完成​課程 0;而且學習課程 0 以前,你還應先完成課程 1。這是不可能的。

說明:

輸入的先決條件是由邊緣列表表示的圖形,而不是鄰接矩陣。詳情請參見圖的表示法。

你能夠假定輸入的先決條件中沒有重複的邊。

(2)   截圖步驟:

本題思路:採用拓撲排序+廣度優先搜索的方式進行求解。

步驟一:對全部節點創建一個入度表times,times[i]表示第i個節點有多少個入度,(這裏入度的意思是當實現此節點時,須要多少個前驅節點的支持)。

步驟二:將入度表中入度爲0的節點添加到隊列que中。

步驟三:取出隊列第一個元素temp;並將times中,以該節點做爲前驅節點的入度減一,並判斷入度是否等於0,若是等於0加入到隊列中。

步驟四:重複步驟三,知道隊列爲空,判斷times中是否存在非0的節點,若是存在則說明有環,不存在說明無環。(其中隊列每次輸出的值就是拓排序的輸出值)

(3)   Java代碼:

class Solution { public boolean canFinish(int numCourses, int[][] prerequisites) { int []times=new int[numCourses]; for(int i=0;i<prerequisites.length;i++) { int num=prerequisites[i][0]; times[num]=times[num]+1; } Queue<Integer> que=new LinkedList<Integer>(); for(int j=0;j<times.length;j++) { if(times[j]==0) { que.add(j); } } while(!que.isEmpty()) { int temp=que.poll(); for(int m=0;m<prerequisites.length;m++) { if(prerequisites[m][1]==temp) { times[prerequisites[m][0]]--; if(times[prerequisites[m][0]]==0) { que.add(prerequisites[m][0]); } } } } for(int e=0;e<times.length;e++) { if(times[e]!=0) { return false; } } return true; } }
相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息