拓撲排序dfs實現

用來進行確定前驅關係。
比如a < b , c < d, c < b 可以確定
a < c < b < d
或者
c < a < b < d

如果沒有環的話一定可以存在一條這樣的鏈,但是如果有環就不能進行拓撲排序。這個例子就是不能 a > b 且 b > a;

使用dfs 進行

僞代碼

//判斷是否有環(true 沒有; false 有)
bool dfs(u) {
	本趟節點標記;
	for(遍歷以u爲入弧的定點){
			if(是本趟節點)return false;
			else if(如果沒訪問過) {
				if(子節點有環)return false;
			}
		}
		//表示這個節點的到底都沒有環
		倒着將沿途的節點加入拓撲隊列    //因爲這是遞歸的返回,就是到頭回來的過程
		return true;
	}
bool topoSort(){
	for(遍歷節點){
		if(沒訪問過){
			if(有環) return false;
		}
	}
	//所有節點都沒環
	return true;
}

兩句if 可以合成爲 
if(沒訪問過 && 有環)return false;


#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

const int maxn = 100;
int c[maxn];
int topo[maxn], t, n;
int G[maxn][maxn];


bool dfs(int u)
{
	c[u] = -1;
	for(int v = 0; v < n; v++)
	{
		if(G[u][v])
		{
			if(c[v] < 0)
				return false;
			else if(!c[v] && !dfs(v))
                return false;
		}
	}
	c[u] = 1;
	topo[--t] = u;
	return true;
}
bool topoSort()
{
	t = n;
	memset(c,0,sizeof(c));
	for(int u = 0; u < n; u++){
		if(!c[u] && !dfs(u))
            return false;
	}
	return true;
}


int main()
{
    char ch[100] = {'a', 'b', 'c', 'd'};
    n = 4;
    G[0][1] = 1;
    //G[1][0] = 1;
    G[2][1] = 1;
    G[3][2] = 1;
    if(!topoSort()){
        printf("無法拓撲排序\n");
        return 0;
    }
    for(int i = 0; i < 4; i++){
        printf("%c ", ch[topo[i]]);
    }
    printf("\n");
}

這個代碼最精彩的部分就是使用c[u] = -1判斷本趟結果是否有環。
區別於經典的dfs標誌數組用了兩個值表示不同的意思。
c[u] = 0:表示每訪問
c[u] = 1:表示上面爲頂點的節點訪問過
c[u] = -1 : 表示以本次dfs是否訪問過

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