1. 程式人生 > >拓撲排序(Topological Sorting)演算法

拓撲排序(Topological Sorting)演算法

拓撲排序(Topological Sorting)

在圖論中,由一個有向無環圖的頂點組成的序列,當且僅當滿足下列條件時,稱為該圖的一個拓撲排序:

  • 每個頂點出現且只出現一次;
  • 若A在序列中排在B的前面,則在圖中不存在從B到A的路徑。

用頂點表示活動,用弧表示活動之間的優先關係,這樣的有向圖為頂點表示活動的網,稱為AOV網(Activity On Vertex Network)
另外,AOV網是一種有向無迴路的圖。那麼,每個AOV網都至少存在一個拓撲排序。

拓撲排序演算法

對AOV網進行拓撲排序的基本思路如下:

  • 從AOV網中選擇一個入度為0的頂點輸出
  • 刪除此頂點,並刪除以此頂點為尾的弧(更新頂點入度)
  • 繼續重複前面兩個步驟,直到全部定點輸出

大概流程圖如下圖所示:
enter image description here

演算法實現

/**
 * @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的頂點入棧的時間複雜度為O(n),之後,每個頂點進一次棧,出一次棧,入度減1的操作共執行了e次,則整個演算法的時間複雜度為O(n+e)