1、定義
用頂點表示活動,用有向邊<Vi, Vj>表示活動間的優先關系。
Vi必須先於活動Vj進行。
這種有向圖叫做頂點表示活動的AOV網絡(Activity On Vertices)
2、拓撲排序
拓撲序列:即將各個頂點(代表各個活動)排列成一個線性有序的序列,使得所有弧尾結點排在弧頭結點的前面。
這種構造AOV網絡全部頂點的拓撲有序序列的運算叫做拓撲排序。
如果通過拓撲排序能將AOV網絡的所有頂點都排入一個拓撲有序的序列中,則一定沒有有向環。
上圖的拓撲排序為:
C1,C8,C2,C3,C5,C9,C4,C7,C6
拓撲排序方法:
(1)輸入AOV網絡。令n為頂點個數;
(2)在AOV網絡中選一個沒有直接前驅的頂點,並輸出之;
(3)從圖中刪去該頂點,同時刪去所有它發出的有向邊;
(4)重復以上(2)(3)步,直到
全部頂點均已輸出,拓撲有序序列形成,拓撲排序完成;
或
圖中還有未輸出的頂點,但已跳出處理循環。說明圖中還剩下一些頂點,它們都有直接前驅,這是網絡中必有環。
如果圖采用鄰接表儲存,則在鄰接表中增設一個數組count[],記錄各頂點入度。入度為0的頂點即無前驅頂點。
在輸入數據前,頂點表data[]和入度數組count[]全部初始化。
在輸入數據時,每輸入一條邊<j, k >,就需要建立一個邊結點,並將它鏈入相應邊鏈表中,統計入度信息:
EdgeNode *p = new EdgeNode; p->adjvex = k; p->nextarc = G.VexList[j].firstarc; data[j].firstarc = p; count[k]++;
在算法中,使用一個存放入度為0的頂點的鏈式棧,供選擇和輸出無前驅的頂點。
算法描述:
建立入度為0的頂點棧;
當入度為0的頂點棧不為空時,重復執行
從頂點棧中推出一個頂點,並輸出之;
從AOV網絡中刪去這個頂點和它發出的邊,邊的總頂點入度減一;
如果邊的終頂點入度減至0,則該頂點進入入度為0的頂點棧;
如果輸出頂點個數少於AOV網絡的頂點個數,則報告網絡中存在有向環。
算法分析:
如果AOV網絡中有n個頂點,e條邊,在拓撲排序的過程中,搜索入度為0的頂點,建立鏈式棧所需要的時間是O(n)。在正常的情況下,有向圖有n個頂點,每個頂點進入一次棧,出一次棧,共輸出n次。頂點入度減一的運算共執行了e次。所以總的時間復雜度為O(n+e).