分類: C/C++
1. 拓撲排序
1) 無環圖:
一個無環的有向圖稱爲無環圖(Directed Acyclic Graph),簡稱DAG圖。
所有的工程或者某種流程都可以分爲若干個小的工程或者階段,稱這些小的工程或階段爲“活動”。
這些子程序之間存在一定的約束,其中某種子工程的開始必須在另一些子工程完成之後。因此DAG圖表示一個工程,其中有向邊表示約束關係。這種有向圖必須是無環的。如果出現了環(有向環),那麼向前遞推,環路上的任一子工程開始的先決條件必然是自己,顯然矛盾的。如果設計出這樣的工程圖,工程無法進行。拓撲排序就是測試一個工程能否順利進行。
若以圖中的頂點來表示活動,有向邊表示活動之間的優先關係,則這樣的有向圖稱爲 AOV(Activity On Vertex network) 網。在 AOV 網中,若從頂點 v i 到頂點 v j 之間存在一條有向路徑,稱頂點 v i 是頂點 v j 的前趨,或者稱頂點 v j 是頂點 v i 的後繼。
2)對 AOV 網進行拓撲排序的方法和步驟如下:
(1)從 AOV 網中選擇一個沒有前趨的頂點(該頂點的入度爲 0 )並且輸出它;
(2)從網中刪去該頂點,並且刪去從該頂點發出的全部有向邊;
(3)重複上述兩步,直到剩餘網中不再存在沒有前趨的頂點爲止。
3)操作的結果有兩種:
一種是網中全部頂點都被輸出,這說明網中不存在有向迴路,拓撲排序成功;
另一種是網中頂點未被全部輸出,剩餘的頂點均有前趨頂點,這說明網中存在有向迴路,不存在拓撲有序序列。
4)算法:
爲了避免在每一步選入度爲零的頂點時重複掃描表頭數組,利用表頭數組中入度爲零的頂點域作爲鏈棧域,存放下一個入度爲零的頂點序號,零表示棧底,棧頂指針爲 top ,寄生在表頭數組的入度域中的入度爲零的頂點:
拓樸排序算法梗概如下:
(1)掃描頂點表,將入度爲零的頂點入棧;
(2)While ( 棧非空 )
{ 將棧頂點 v j 彈出並輸出之;
在鄰接鏈表中查 v j 的直接後繼 v k ,把 v k 的入度減 1 ,若 v k 的入度爲零則進棧;
}
5)算法的時間複雜度
對一個具有 n 個頂點, e 條邊的網來說,初始建立入度爲零的頂點棧,要檢查所有頂點一次,執行時間爲 O(n) ;排序中,若 AOV 網無迴路,則每個頂點入、出棧各一次,每個表結點被檢查一次,因而執行時間是 O(n+e) 。所以,整個算法的時間複雜度是 O(n+e) 。
2.關鍵路徑
若在帶權的有向圖中,以頂點表示事件,以有向邊表示活動,邊上的權值表示活動的開銷(如該活動持續時間),則此帶權的有向圖稱爲邊表示活動的網 (Activity on Edge Network) ,簡稱 AOE 網。
1) AOV 網具有的性質
(1)只有在某頂點所代表的事件發生後,從該頂點出發的各有向邊所代表的活動才能開始。
(2)只有在進入某一頂點的各有向邊所代表的活動都已經結束,該頂點所代表的事件才能發生。
(3)表示實際工程計劃的 AOE 網應該是無環的,並且存在唯一的入度過爲 0 的開始頂點和唯一的出度爲 0 的完成頂點。
2)關鍵活動:
由事件 v j 的最早發生時間和最晚發生時間的定義 , 可以採取如下步驟求得關鍵活動 :
(1)從開始頂點 v 1 出發 , 令 ve(1)=0, 按拓樸有序序列求其餘各頂點的可能最早發生時間。
Ve(k)=max{ve(j)+dut()} 其中dut(表示頂點Vj到頂點Vk所持續的時間;
j ∈ T
其中 T 是以頂點 v k 爲尾的所有弧的頭頂點的集合 (2 ≤ k ≤ n) 。
如果得到的拓樸有序序列中頂點的個數小於網中頂點個數 n ,則說明網中有環,不能求出關鍵路徑,算法結束。
(2)從完成頂點 v n 出發,令 vl(n)=ve(n) ,按逆拓樸有序求其餘各頂點的允許的最晚發生時間 :
vl(j)=min{vl(k)-dut()}
k ∈ S
其中 S 是以頂點 v j 是頭的所有弧的尾頂點集合 (1 ≤ j ≤ n-1) 。
(3)求每一項活動 a i (1 ≤ i ≤ m) 的最早開始時間 e(i)=ve(j) ;最晚開始時間
l(i)=vl(k)-dut()
若某條弧滿足 e(i)=l(i) ,則它是關鍵活動。
求出 AOE 網中所有關鍵活動後,只要刪去 AOE 網中所有的非關鍵活動,即可得到 AOE 網的關鍵路徑。
這時從開始頂點到達完成頂點的所有路徑都是關鍵路徑。一個 AOE 網的關鍵路徑可以不止一條。
3)注意:
並不是加快任何一個關鍵活動都可以縮短整個工程完成的時間,只有加快那些包括在所有的關鍵路徑上的關鍵活動才能達到這個目的。只有在不改變 AOE 網的關鍵路徑的前提下,加快包含在關鍵路徑上的關鍵活動纔可以縮短整個工程的完成時間。