拓撲排序

概念

拓撲排序是將有向無環圖G的所有頂點排成一個線性序列,使得對圖G的任意兩個頂點u、v,如果存在邊u->v,那麼在序列中u一定在v的前面,這個序列稱爲拓撲序列

步驟

(1)定義一個隊列Q,並把所有入度爲0的結點加入隊列;
(2)取隊首結點,輸出。然後刪去所有從它出發的邊,並令這些邊到達的頂點的入度減1,如果某個頂點的入度減爲0,則將其加入隊列。
(3)反覆進行(2)操作,直到隊列爲空。如果隊列爲空時入過隊的結點數目恰好爲N,說明拓撲排序成功,圖G爲有向無環圖;否則,拓撲排序失敗,圖G中有環。

實例演示

引用自:https://blog.csdn.net/qq_35644234/article/details/60578189utm_source=distribute.pc_relevant.none-task

如果我們有如下的一個有向無環圖,我們需要對這個圖的頂點進行拓撲排序,過程如下:
這裏寫圖片描述

首先,我們發現V6和v1是沒有前驅的,所以我們就隨機選去一個輸出,我們先輸出V6,刪除和V6有關的邊,得到如下圖結果:
這裏寫圖片描述

然後,我們繼續尋找沒有前驅的頂點,發現V1沒有前驅,所以輸出V1,刪除和V1有關的邊,得到下圖的結果:
這裏寫圖片描述

然後,我們又發現V4和V3都是沒有前驅的,那麼我們就隨機選取一個頂點輸出(具體看你實現的算法和圖存儲結構),我們輸出V4,得到如下圖結果:
這裏寫圖片描述

然後,我們輸出沒有前驅的頂點V3,得到如下結果:
這裏寫圖片描述

然後,我們分別輸出V5和V2,最後全部頂點輸出完成,該圖的一個拓撲序列爲:

v6–>v1—->v4—>v3—>v5—>v2

實現代碼

vector<int> adj[maxv]; //鄰接表
int n,m,inDegree[maxv];  //頂點數,入度
bool topologicalSort(){
	int num=0; //記錄加入拓撲序列的頂點數
	queue<int> q;
	for(int i=0;i<n;i++){
		if(inDegree[i]==0) q.push(i);
	} 
	while(!q.empty()){
		int u=q.front();
		//printf("%d",u)  //可輸出該頂點 
		q.pop();
		for(int i=0;i<adj[u].size();i++){
			int v=adj[u][i];
			inDegree[v]--;
			if(inDegree[v]==0) q.push(v); 
		}
		adj[u].clear(); //清空頂點u的所有出邊(如果沒有必要可以不寫) 
		num++;  //加入拓撲序列的頂點數加1 
	}
	return num==n?true:false;
}

注:如果要求有多個入度爲0的頂點時選擇編號最小的頂點,可以把queue改爲priority_queue,並使用小頂堆。(改爲set也可以)

重要應用

拓撲排序的很重要的應用就是判斷一個給定的圖是否是有向無環圖。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章