DAG是一種有向無環圖,可以用來表示各種事務執行的先後順序,而拓撲排序的作用就是找到恰當的工作順序,使得對於所有有向邊<u,v>,都保證頂點u出現在頂點v之前。具體的拓撲排序的形象解釋我這裏就不多廢話了,下面直接附上兩種搜索形式下的拓撲排序:
1.廣度優先搜索實現的拓撲排序:
#include<iostream>
#include<queue>
#include<list>
using namespace std;
#define Max 10000
int N;
bool visited[Max];
vector<int> G[Max];
int indeg[Max];
list<int> out;
void bfs(int x)
{
queue<int> q;
q.push(x);
visited[x]=true;
while(!q.empty())
{
int u=q.front();q.pop();
out.push_back(u);
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i];
indeg[v]--; //刪除當前訪問節點的所有出邊,並將其後繼節點的入度減一
if(indeg[v]==0 && !visited[v]) //若後繼節點中有入度爲0並且未訪問的,那麼就將這個點放在
{ //隊列中,當做之後的拓撲排序的節點
visited[v]=true;
q.push(v);
}
}
}
}
void topologicalSort()
{
for(int i=0;i<N;i++)
{
visited[i]=false;
}
for(int u=0;u<N;u++)
{
if(indeg[u]==0 && !visited[u]) //找到入度爲0並且未訪問的點進行bfs
bfs(u);
}
for(list<int>::iterator it=out.begin();it!=out.end();it++)
{
cout<<(*it)<<" ";
}
}
int main()
{
int start,end,M;
cin>>N>>M;
for(int i=0;i<M;i++)
{
cin>>start>>end;
G[start].push_back(end);
indeg[end]++;
}
topologicalSort();
return 0;
}
2.深度優先搜索實現的拓撲排序:
#include<iostream>
#include<queue>
#include<list>
using namespace std;
#define Max 10000
int N;
bool visited[Max];
vector<int> G[Max];
list<int> out;
void dfs(int u)
{
cout<<u<<endl;
visited[u]=true;
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i];
if(!visited[v])
dfs(v);
}
out.push_front(u);
//和廣度優先搜索中不一樣,bfs是就是按照拓撲順序,從前往後找,找到入度爲0的頂點就進行輸出
//而深度優先搜索dfs則是從後往前推,在不斷深入圖,找到最後沒有後繼結點,就放在輸出隊列一開始,
//之後在不斷遞歸返回時,再將其他沒有後繼節點的節點放在輸出隊列的開頭,那麼這樣就會保證一開始
//進入輸出隊列的最深處的節點在最後輸出,保證滿足拓撲順序
}
void topologicalSort()
{
for(int i=0;i<N;i++)
{
visited[i]=false;
}
for(int u=0;u<N;u++)
{
if(!visited[u])
dfs(u);
}
for(list<int>::iterator it=out.begin();it!=out.end();it++)
{
cout<<(*it)<<" ";
}
}
int main()
{
int start,end,M;
cin>>N>>M;
for(int i=0;i<M;i++)
{
cin>>start>>end;
G[start].push_back(end);
}
topologicalSort();
return 0;
}
對於拓撲排序,大家要知道的是,對於同一個DAG,其拓撲排序的結果可能不止一種,這裏的廣度和深度在確定了相同情況下先輸出小編號的頂點或者大編號的頂點,所以只會輸出一種結果,具體的對於求解所有的拓撲排序的結果,我之後會找個時間學習,並附上代碼.
PS:這三月份以來,事情就特別多,首先本創結題,其次是準備江蘇省計算機三級,準備了一個星期,才發現考試真的是水,心碎~之後我還是會堅持寫博客~