引言
發現普林斯頓那本算法和算法導論都側重於用介紹用DFS實現拓撲排序,所以這一篇文章我們來着重套路下用隊列實現拓撲排序的Khan算法。
核心思想
有向圖中的每個節點有入度和出度這兩個屬性,如一個只包含a和b的有向圖中,a到b有且僅有一條邊則稱b的入度等於 1,而a的出度爲1。出度爲0的頂點不可能到達其他的頂點,這樣的頂點稱爲終點(sink),同樣入度爲0的頂點不可能被任何其他頂點到達,這樣的頂點稱爲起點(source)。
khan算法利用上面的結論首先將圖中所有起點存入集合,同時構建一個入度表儲存所有節點的入度,然後重複的將隊列中的起點出隊放入集合來儲存排序的結果,最後將該節點的所有鄰居節在入度表中的入度-1再判斷該節點的入度是否爲零,如果是則將他存進起點集合,然後重複這個操作。
算法實現(僞代碼)
public Stack topologicalSort(Graph graph) {
Queue sources = new LinkedList();
Map degrees = new HashMap();
for (int v : graph.vertexSet()){
int d = graph.inDegree(v);
if (d == 0){
sources.add(v);
}
degrees.put(v,d);
}
Stack topSorted = new Stack();
int count = 0;
while(!sources.isEmpty()){
int v = sources.poll();
topSorted.add(v);
for (int adj : graph.adj(v)){
int degree = degrees.get(v) - 1;
if (degree == 0){
sources.add(adj);
} else {
degrees.put(adj,degree);
}
}
count += 1;
}
//是否有環
if (count!=graph.vertexSet.size()){
throw new HasCycleException();
}
return topSorted;
}
算法特性
可以在線性時間內排序並判斷圖中是否有環