算法與數據結構基礎 - 拓撲排序(Topological Sort)

拓撲排序基礎css

拓撲排序用於解決有向無環圖(DAG,Directed Acyclic Graph)按依賴關係排線性序列問題,直白地說解決這樣的問題:有一組數據,其中一些數據依賴其餘,問可否按依賴關係排序(被依賴的排在前面),或給出排序結果。html

 

最經常使用解決拓撲排序問題的方法是Kahn算法,步驟能夠歸納爲:node

1. 根據依賴關係,構建鄰接矩陣或鄰接表、入度數組
2. 取入度爲0的數據(即不依賴其餘數據的數據),根據鄰接矩陣/鄰接表依次減少依賴其的數據的入度
3. 判斷減少後是否有新的入度爲0的數據,繼續進行第2步
4. 直到全部數據入度爲0、獲得拓撲排序序列,或返回失敗(存在環形依賴)

其中二、3兩個步驟取入度爲0數據、減少依賴其的數據的入度,過程像樹的寬度優先搜索,用到相似BFS方法;以上過程用僞代碼表示以下:git

L ← Empty list that will contain the sorted elements
S ← Set of all nodes with no incoming edge
while S is non-empty do
    remove a node n from S
    add n to tail of L
    for each node m with an edge e from n to m do
        remove edge e from the graph
        if m has no other incoming edges then
            insert m into S
if graph has edges then
    return error   (graph has at least one cycle)
else 
    return L   (a topologically sorted order)

 

下面看具體例子 207. Course Schedule (有n個課程,課程間有依賴關係,問可否完成全部課程):github

    //207. Course Schedule
    bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
//構建鄰接矩陣、入度數組 vector
<vector<int>> adj(numCourses); vector<int> indegree(numCourses,0); for(auto x:prerequisites){ adj[x.second].push_back(x.first); indegree[x.first]++; }
//相似BFS queue
<int> q; for(int i=0;i<numCourses;i++) if(indegree[i]==0) q.push(i); while(!q.empty()){ int cur=q.front(); q.pop(); numCourses--; for(auto next:adj[cur]) if(--indegree[next]==0) q.push(next);//新入度爲0的先處理,這與正統BFS有區別 }
//判斷最後全部數據入度爲0
return numCourses==0; }

以上用到鄰接矩陣(adjacency matrix)表示依賴關係,時間複雜度爲O(V^2),其中V爲數據個數。可視化過程:這裏算法

 

相關LeetCode題:數組

207. Course Schedule  題解ui

210. Course Schedule II  題解spa

444. Sequence Reconstruction  題解3d

269. Alien Dictionary  題解

相關文章
相關標籤/搜索