拓扑排序(Topological Sorting)
拓撲排序(Topological Sorting)
這篇文章我們來講一下拓撲排序,這可是一個很重要也很實用的算法,面試中常考,工作中常用,無論是互聯(lián)網公司還是金融公司,考算法的時候都賊喜歡問這個。
拓撲排序其實并不是一個傳統(tǒng)意義上的排序算法,它是針對AOV網線性輸出的過程,所以我們先來了解一下AOV網是什么東西。
AOV網
拓撲排序算法只適用于AOV網,它是一種有向無環(huán)圖,那么到底什么是AOV網呢?
在日常生活中,一項大工程可以看作是由若干個小工程組成的,但這些小工程之間必定存在一些先后順序,也就是說,有些工程必須在其它一些工程完成之后才能開始。我們可以用有向圖來形象地表示這些工程之間的先后關系,小工程為頂點,之間的先后關系為有向邊,繪制成的有向圖就是AOV網。一個AOV網必定是一個有向無環(huán)圖,也就是不應該帶有回路,否則就會出現先后關系的自相矛盾。
例如,假定一個計算機專業(yè)的學生必須完成下圖所列出的全部課程。
在這里,每個課程就代表一個小工程,學習一門課程就表示進行一項工程,學習每門課程的先決條件是學完它的全部先修課程。如學習《高等數學》課程則可以隨時安排,因為它是基礎課程,沒有先修課。學習《數據結構》課程就必須安排在學完它的兩門先修課程《離散數學》和《算法語言》之后。
若用AOV網來表示這種課程安排的先后關系,則如上圖所示。圖中的每個頂點代表一門課程,每條有向邊代表起點對應的課程是終點對應課程的先修課。從圖中可以清楚地看出各課程之間的先修和后續(xù)的關系。如課程C5的先修課為C2,后續(xù)課程為C4和C6。
拓撲排序
那么拓撲排序到底是干什么的呢?如果我們要安排課表,那么不可能直接把AOV圖給學生看,而是需要把它排成一個序列,使得每個課程的先修課都排在該課程的前面,這個過程就稱為“拓撲排序”。拓撲排序得到的序列并不是唯一的,就好像你早上穿衣服可以先穿內衣再穿外套,然后再穿褲子,也可以先穿褲子再穿內衣,最后再穿外套,只要內衣在外套之前穿就行。
拓撲排序得到的序列可以幫助我們合理安排一個工程的進度,所以,由AOV網構造拓撲序列具有很高的實際應用價值。
算法思想
構造拓撲序列的拓撲排序算法思想很簡單:
(1)選擇一個入度為0的頂點;
(2)從AOV網中刪除此頂點及以此頂點為起點的關聯(lián)邊;
(3)重復上述兩步直到不存在入度為0的頂點為止;
(4)若AOV網中還有頂點,則說明有向圖存在回路。
算法實現
class Graph {int V; // 頂點個數 int* indegree; // 頂點入度 list<int> *adj; // 鄰接表 public:Graph(int v) {this->V = v;this->adj = new list<int>[v];this->indegree = new int[v];for(int i = 0; i < v; i++) {this->indegree[i] = 0;}}~Graph() {delete [] this->adj;delete [] this->indegree;}void addEdge(int v, int w) {this->adj[v].push_back(w);this->indegree[w]++;}vector<int> topologicalSort() {vector<int> res; // 拓撲序列 queue<int> que; // 入度為0頂點集合 for(int i = 0; i < this->V; i++) {if (this->indegree[i] == 0) {que.push(i);}}while(!que.empty()) {int front = que.front();que.pop();res.push_back(front);for(int item:this->adj[front]) {if (!(--this->indegree[item])) {que.push(item);}}}return res.size() == this->V ? res : vector<int> ();} };測試
int main(){Graph graph(8);graph.addEdge(0,1);graph.addEdge(0,2);graph.addEdge(2,4);graph.addEdge(1,4);graph.addEdge(1,3);graph.addEdge(4,3);graph.addEdge(4,5);graph.addEdge(4,6);graph.addEdge(3,5);graph.addEdge(6,7);graph.addEdge(5,7);graph.addEdge(3,7);for (int item:graph.topologicalSort()) {cout << item << " ";}return 0; }
練習題
LeetCode 1203.項目管理
總結
以上是生活随笔為你收集整理的拓扑排序(Topological Sorting)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Winddows 10 安装 COCO
- 下一篇: 并查集(Union Find Set)