在正文開始前,咱們先來了解一下有向無環圖(Directed Acyclic Graph簡稱DAG)算法
以下圖就是一個DAG圖,DAG圖是咱們討論拓撲排序的基礎。jsp
AOV網:數據在頂點 能夠理解爲面向對象
AOE網:數據在邊上,能夠理解爲面向過程!
拓撲排序(Topological Order),不少人據說過,可是不瞭解的一種算法。或許不少人只知道它是圖論的一種排序,至於幹什麼的不清楚。又或許不少人可能還會認爲它是一種啥排序。學習
而實質上它只是將DAG圖的頂點排成一個線性序列,獲得一個頂點的全序集合。其排序的順序依據就是節點的指向關係。好比前言的DAG圖:優化
那麼最後獲得的節點的線性序列結果,也必定要知足上面的指向順序。spa
每個節點都擁有入度(有多少點導向它,也就是開始它有多少前提)和出度(它導向多少點,也就是它是多少其餘節點開始的前提)。例如節點5的入度爲3和4,出度爲7。設計
拓撲排序的結果不是惟一的,只要符合上面的條件,那麼它就是拓撲序列,好比1 2 4 3 6 5 7 9
和2 1 3 4 5 6 7 9
,這兩個結果都是可行的。code
官方一點的定義:將有向圖中的節點以線性方式進行排序。即對於任何鏈接自節點u到節點v的有向邊uv,在最後的排序結果中,節點u老是在節點v的前面。
看了上面關於拓撲排序的概念若是還以爲十分抽象的話,那麼不妨考慮一個很是很是經典的例子——選課。對象
假設我很是想學習一門《jsp入門》的課程,可是在修這麼課程以前,咱們必需要學習一些基礎課程,好比《JAVA語言程序設計》,《HTML指南》等等。那麼這個制定選修課程順序的過程,實際上就是一個拓撲排序的過程,每門課程至關於有向圖中的一個頂點,而鏈接頂點之間的有向邊就是課程學習的前後關係。排序
只不過這個過程不是那麼複雜,從而很天然的在咱們的大腦中完成了。將這個過程以算法的形式描述出來的結果,就是拓撲排序。遞歸
能夠看到,上圖中的學習順序,就是拓撲序列,其不止一個結果。
拓撲排序算法在工程學中十分重要。
節點成環的圖,沒法被拓撲排序,由於這在工程上自己沒有意義,好比A——>B——>C——>A,那麼這個工程永遠沒法被開始。
拓撲排序的最優時間複雜度是O(m+n),其中m和n是DAG圖中節點數和邊數。由於拓撲排序至少要對DAG圖的節點和邊進行一次完整的遍歷。
拓撲排序的最優空間複雜度是O(m+n),其中m和n是DAG圖中節點數和邊數。咱們通常使用鄰接表來存儲DAG圖,所以空間複雜度是O(m+n)。
廣度優先搜索法的思路很簡單:
以下圖
若是有時候,咱們只須要知道某個DAG圖是否能夠拓撲排序,而不須要真正獲得拓撲排序後的結果,那麼能夠不須要結果集列表,只須要統計被刪除的節點的數量便可,若是該數量等於DAG圖的節點數,那麼DAG圖能夠被拓撲排序。
深度優先搜索法是廣度優先搜索法的逆向思路,它的步驟以下:
尋找節點A的鄰接點(沿着箭頭指向尋找相鄰的節點)
若是A存在鄰接點
若是有時候,咱們只須要知道某個DAG圖是否能夠拓撲排序,而不須要真正獲得拓撲排序後的結果,那麼能夠不須要結果棧,只須要判斷整個深度優先搜索過程,沒有發生「搜索中」節點的相鄰節點(不包含來路的節點)也是「搜索中」就行。