版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_26760433/article/details/84242686
这里给大家介绍另外一种拓扑排序,这种是基于深搜实现的。
上图:
如果我们按照节点编号顺序从节点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)。
这里总结一下拓扑排序:
*必须是有向图
*必须是无环图
*支持非连通图
*不用考虑权值