1. 程式人生 > >【圖(下)】拓撲排序

【圖(下)】拓撲排序

1、舉例說明:計算機專業排課

在這裡插入圖片描從述
說明:學C1,C2是不需要提前學別的課程的,學C3則需要提前學C1,C2。

把課程列表轉換為圖,其中頂點代表課程,則從V到W有一條邊代表:V是W的預修課程

2、拓撲排序

  • 拓撲序:如果圖中從V到W有一條有向路徑,則V一定排在W之前。滿足此條件的頂點序列稱為一個拓撲序
  • 獲得一個拓撲序的過程就是拓撲排序
  • AOV如果有合理的拓撲序,則必定是有向無環圖(Directed Acyclic Graph, DAG)
    在這裡插入圖片描述

3、演算法

在這裡插入圖片描述

void TopSort()
{
	for (cnt = 0; cnt <
|V| ; cnt++) { V = 未輸出的入度為0的頂點;// O(|V|) if (這樣的V不存在)//外迴圈沒結束已經找不到入度為0的頂點了,有環 { Error(“圖中有迴路”); break; } 輸出V,或者記錄V的輸出序號; for (V 的每個鄰接點W) Indegree[W]––;//相當於去掉從V到W的邊 } }

在TopSort函式中,如果外迴圈還沒結束,就已經找不到“未輸出的入度為0的頂點”,則說明圖中必定存在迴路。

時間複雜度:T = O( |V|2 )

4、聰明的演算法

隨時將入度變為0的頂點放到一個容器裡

void
TopSort() { for (圖中每個頂點V) if (Indegree[V] == 0) Enqueue(V, Q); while (!IsEmpty(Q)) { V = Dequeue(Q); 輸出V,或者記錄V的輸出序號; cnt++;//計數器增加 for (V 的每個鄰接點W)//將V放入容器,V發出的邊斷開,V的鄰接點入度減1 if (––Indegree[W] == 0) Enqueue(W, Q); } if (cnt != |V| ) Error(“圖中有迴路”); }

隨時將入度為0的節點放入容器中,每次從容器中取出元素,保證都是入度為0。

時間複雜度:每個點被訪問一遍,每條邊訪問一遍
T = O( |V| + |E| )

此演算法可以用來檢測有向圖是否DAG(有向無環圖Directed Acyclic Graph)

5、關鍵路徑問題

  • AOE (Activity On Edge) 網路
    一般用於安排專案的工序
    在這裡插入圖片描述
    每條邊代表一個工序或者一個活動
    邊表示活動,頂點表示到達這個頂點時,活動結束了。

頂點的上面部分表示這項工作最早在什麼時間完成,下面的表示這項工作最晚什麼時間開始。
在這裡插入圖片描述
在這裡插入圖片描述
機動時間:不用那麼趕工期,以頂點0到頂點2為例,最早第0天開始工作,最晚第六天完成,而完成這項工作只需要4天時間,就有2天的機動時間。
關鍵路徑:由絕對不允許延誤的活動組成的路徑