1. 程式人生 > >如何理解拓撲排序演算法(轉)

如何理解拓撲排序演算法(轉)

       對於一條有向邊(u,v),定義u < v;滿足所有這樣條件的結點序列稱為拓撲序列。拓撲排序就是求一個有向圖的拓撲序列的演算法。
一個有向圖頂點的拓撲序列不是惟一的。並不是任何有向圖的頂點都可以排成拓撲序列,有環圖是不能排的。


例子:比如排課問題,比如士兵排隊問題等。
         拓撲排序在實際生活中和演算法中都有很大的應用。比如要排一下幾門課程的先後次序,我們可以把課程抽象成結點,把什麼課是什麼課的基礎抽象成邊,那麼該圖的一個拓撲序列就是這些課的一個可行的先後次序。各種語言的編譯器都用到了拓撲排序。
    數學基礎:
        什麼是拓撲排序(Topological Sort)?簡單地說,由某個集合上的一個偏序得到該集合上的一個全序,這個操作稱之為拓撲排序。
    回顧離散數學中關於偏序和全序的定義:
        若集合X上的關係R是自反的、反對稱的和傳遞的,則稱只是集合X上的偏序關係。
        設R是集合X上的偏序(Partial Order),如果對每個x,y∈X必有xRy或yRx,則稱R是集合X上的全序關係。
        直觀地看,偏序指集合中僅有部分成員之間可比較,而全序指集合中全體成員之間均可比較。[例如],圖7.25所示的兩個有向圖,圖中弧(x,y)表示x≤y,則(a)表示偏序,(b)表示全序。若在(a)的有向圖上人為地加一個表示v2≤v3的弧(符號“≤”表示v2領先於v3),則(a)表示的亦為全序,且這個全序稱為拓撲有序(Topological Order),而由偏序定義得到拓撲有序的操作便是拓撲排序。

     ToplogicalSort.gif

 
AOV-網及其拓撲有序序列產生的過程
(a)AOV-網;(b)輸出v6之後;(c)輸出v1之後;(d)輸出v4之後;(e)輸出v3之後;(f)輸出v2之後

    [思想]:
    一、從有向圖中選取一個沒有前驅的頂點,並輸出之;
    二、從有向圖中刪去此頂點以及所有以它為尾的弧;
    重複上述兩步,直至圖空,或者圖不空但找不到無前驅的頂點為止。沒有前驅 -- 入度為零,刪除頂點及以它為尾的弧-- 弧頭頂點的入度減1。

Status Topological Sort(ALGraph G){
    //有向圖G採用鄰接表儲存結構。
    //若G無迴路,則輸出G的頂點的1個拓撲序列並返回OK,否則ERROR。
FindInDegree(G,indegree); //對各頂點求入度indegree[0..vernum-1] InitStack(S); for(i=0;i<G.vexnum; ++i) if(!indegree[i])Push(S,i) //建零入度頂點棧,s入度為0者進棧 count=0//對輸出頂點計數 while (!StackEmpty(S)) { Pop(S,i); printf(i,G.vertices[i].data); ++count; //
輸出i號頂點並計數 for(p=G.vertices[i].firstarc;p; p=p—>nextarc) { k=p—>adivex; //對i號頂點的每個鄰接點的入度減1 if(!(--indegree[k]))Push(S,k);//若入度減為0,則入棧 }//for }//while if(count<G.vexnum) return ERROR; //該有向圖有迴路 else return OK; }//TopologicalSort

思想:

維護一個頂點入度為0的棧,

每次取棧頂元素top輸出,對於top相鄰的點進行入度數-1處理,處理後如果度數為0,再次入棧.

執行n次出棧操作,便可輸出一個圖的拓撲序.

判斷是否包含有向環:如果入度為0的棧為空(top==-1),則說明包含有向環.(證明:無環時總有點入度為0).

時間複雜度:

1.搜尋入度為0的頂點,建棧所需時間O(n);

2.無有向環時,每個頂點入棧一次,出棧一次,每條邊掃描一次且僅一次,時間複雜度O(m).

3.總複雜度:O(n+m).

演算法 ,總的時間複雜度為O(n+e)。

作者: 自由、創新、研究、探索……
出處:http://shanyou.cnblogs.com/
版權:本文版權歸作者和部落格園共有
轉載:歡迎轉載,為了儲存作者的創作熱情,請按要求【轉載】,謝謝
要求:未經作者同意,必須保留此段宣告;必須在文章中給出原文連線;否則必究法律責任