拓撲排序基礎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題:數組