拓撲排序(Topological Sorting)演算法
阿新 • • 發佈:2019-01-25
拓撲排序(Topological Sorting)
在圖論中,由一個有向無環圖的頂點組成的序列,當且僅當滿足下列條件時,稱為該圖的一個拓撲排序:
- 每個頂點出現且只出現一次;
- 若A在序列中排在B的前面,則在圖中不存在從B到A的路徑。
用頂點表示活動,用弧表示活動之間的優先關係,這樣的有向圖為頂點表示活動的網,稱為AOV網(Activity On Vertex Network)。
另外,AOV網是一種有向無迴路的圖。那麼,每個AOV網都至少存在一個拓撲排序。
拓撲排序演算法
對AOV網進行拓撲排序的基本思路如下:
- 從AOV網中選擇一個入度為0的頂點輸出
- 刪除此頂點,並刪除以此頂點為尾的弧(更新頂點入度)
- 繼續重複前面兩個步驟,直到全部定點輸出
大概流程圖如下圖所示:
演算法實現
/**
* @description 拓撲排序演算法(TopologicalSort)
* 輸入:領接表表示的有向圖
* 輸出:若圖無迴路,則輸出拓撲排序序列並返回OK
* 若圖有迴路,則返回ERROR.
* @author GongchuangSu
* @since 2016.04.19
* @version v1.0
*/
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
public class TopologicalSort {
Stack < Integer > stack; // 用於儲存入度為0的頂點的下標
Queue < Integer > queue; // 用於儲存拓撲排序結果
int vlen; // 頂點個數
int[] indegree; // 入度陣列
int count; // 統計輸出頂點個數
public String topologicalSort(ListDG listDG) {
stack = new Stack < Integer > ();
queue = new LinkedList < Integer > ();
this.vlen = listDG.vlen;
indegree = new int[vlen];
// 統計每個頂點的入度數
for (int i = 0; i < vlen; i++) {
ListDG.EdgeNode edgeNode = new ListDG.EdgeNode();
edgeNode = listDG.vertexNodeList[i].firstedge;
while (edgeNode != null) {
indegree[edgeNode.adjvex]++;
edgeNode = edgeNode.next;
}
}
// 將入度為0的頂點入棧
for (int i = 0; i < vlen; i++) {
if (indegree[i] == 0)
stack.push(i);
}
while (!stack.isEmpty()) {
int top = stack.pop(); // 出棧
queue.offer(top);
count++; // 統計輸出頂點個數
ListDG.EdgeNode edgeNode = new ListDG.EdgeNode();
edgeNode = listDG.vertexNodeList[top].firstedge;
while (edgeNode != null) {
indegree[edgeNode.adjvex]--; // 與此頂點連線的各頂點入度減1
if (indegree[edgeNode.adjvex] == 0) // 判斷連線頂點的入度是否為0,若為0,則入棧
stack.push(edgeNode.adjvex);
edgeNode = edgeNode.next;
}
}
// 判斷是否存在環
if (count != vlen) {
System.out.print("Graph has a cycle.\n");
return "Error";
} else {
System.out.print(queue);
return "OK";
}
}
}
原始碼下載:拓撲排序
時間複雜度
對於一個具有n個頂點e條弧的AOV網來說,將入度為0的頂點入棧的時間複雜度為