拓撲排序(深搜實現)
阿新 • • 發佈:2018-11-29
這裡給大家介紹另外一種拓撲排序,這種是基於深搜實現的。
上圖:
如果我們按照節點編號順序從節點0開始深度優先搜尋,就會得到下面這個序列。
5,6,3,2,8,7,0,4,1
把這個序列逆置一下,就會發現這是一個正確的拓撲序列。(可以好好想一下這個結論,我當時想了很久)
1,4,0,7,8,2,3,6,5
貼程式碼
#include<vector>
#include<iostream>
using namespace std;
class Graph
{
public:
int v; //頂點個數
vector< int> *adj; //鄰接表
int *mark; //如果訪問過,標記為1,否則為0
Graph(int n); //建構函式
~Graph(); //解構函式
void addEdge(int start,int end); //新增邊
void TopsortbyDFS(); //拓撲排序
};
Graph::Graph(int n) //建構函式
{
v=n;
adj=new vector<int>[n];
mark=new int[n];
for(int i=0;i<n;i++) //將所有頂點標記置為0,表示沒有訪問過
mark[i]=0;
}
Graph::~Graph() //解構函式
{
delete [] adj;
delete [] mark;
}
void Graph::addEdge(int s,int e)
{
adj[s].push_back(e); //新增邊
}
void Do_topsort(Graph & g,int node,int *result,int &index) //核心演算法,引數分別為 (圖
{ //g,當前訪問的頂點,儲存結果陣列,陣列下標) 注意index要為引用
g.mark[node]=1; //已訪問標記為1
for( vector<int>::iterator ii=g.adj[node].begin();ii!=g.adj[node].end();ii++ )
{
if(g.mark[*ii] == 0) //如果該頂點的相鄰頂點沒有被訪問
{
Do_topsort(g,*ii,result,index);
}
}
result[index++]=node; //相當於後處理
}
void Graph::TopsortbyDFS()
{
int *result = new int[v]; //將結果儲存在result陣列中,待會逆序輸出就是拓撲序列
int index=0; //result下標初始化為0
for(int i=0;i<v;i++) //對所有頂點進行深搜
{
if(mark[i]==0) //如果mark為0,說明沒有訪問過
{
Do_topsort(*this,i,result,index); //遞迴函式
}
}
for(int i=v-1;i>=0;i--) //逆序輸出
cout<<result[i]<<" ";
}
int main()
{
Graph g(9);
g.addEdge(0,2);
g.addEdge(0,7);
g.addEdge(1,2);
g.addEdge(1,4);
g.addEdge(1,3);
g.addEdge(2,3);
g.addEdge(3,5);
g.addEdge(3,6);
g.addEdge(4,5);
g.addEdge(7,8);
g.addEdge(8,6);
g.TopsortbyDFS();
return 0;
}
執行結果:
時間複雜度和佇列方法實現相同都為O(n+e)。
這裡總結一下拓撲排序:
*必須是有向圖
*必須是無環圖
*支援非連通圖
*不用考慮權值