算法和数据结构——高等图算法(拓扑排序)

有向无环图DAG可用来表示各种事物的顺序。比如以各项工作为顶点,有向边来表示工作顺序。

 上图中我们着手处理工作B之前需要先处理完成工作A和工作X,如果对这种表示顺序关系的DAG进行拓扑排序,我们便可以得到一个恰当的工作排序,对于一个有向无环图DAG,只要存在边(u,v),就让u在线性序列中位于v之前,这就是拓扑排序。

所谓图的拓扑排序,就是让图中全部有向边都由左向右,同时将所有顶点排列在一条水平线上。如上图的工作安排,就可以完成所有准备工作。

应用深度优先或广度优先能够较简单的实现拓扑排序。

下面是广度优先搜索实现拓扑排序。

#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
#include<list>
using namespace std;
static const int MAX = 100000;
static const int INFTY = (1<<29);
vector<int>G[MAX];//邻接链表
list<int>out;
bool V[MAX];
int N;
int indeg[MAX];//indeg[i]记录i的入度数
void bfs(int s){
	queue<int>q;
	q.push(s);//进入队列
	V[s]=true;//该点已被记录
	while(!q.empty()){
		int u=q.front();
		q.pop();
		out.push_back(u);
		//完成u点之后要斩断与u有关的点的问题 
		for(int i=0;i<G[u].size();i++){
			int v=G[u][i];
			//v的入度减少 
			indeg[v]--;
			//如果点v的入度为零且是没有选择过的
			//那么下一个就该安排它了 
			if(indeg[v]==0&&!V[v]){
				V[v]=true;
				q.push(v);
			}		
		}
	}
} 
void tsort(){
	//初始化入度数
	for(int i=0;i<N;i++){
		indeg[i]=0; 
	}
	for(int u=0;u<N;u++){
		//统计结点u到达所有点的入度 
		for(int i=0;i<G[u].size();i++){
			int v=G[u][i];
			indeg[v]++;
		}
	} 
	for(int u=0;u<N;u++){
		//没有入度则直接安排 
		if(indeg[u]==0&&!V[u])
			bfs(u);
	}
	for(list<int>::iterator it = out.begin();it!=out.end();it++){
		cout<<*it<<endl;
	} 
} 
int main(){
	int s,t,M;
	cin>>N>>M;
	for(int i=0;i<N;i++){
		V[i]=false;
	}
	for(int i=0;i<N;i++){
		cin>>s>>t;
		G[s].push_back(t);
	}
	tsort();
	return 0;
}
/*
6 6
0 1
1 2
3 1
3 4
4 5
5 2
0
3
1
4
5
2
*/ 

以下是深度优先搜索实现拓扑排序。

#include<iostream>
#include<vector>
#include<list>
#include<algorithm>
using namespace std;
static const int MAX = 100000;
int N;
list<int>out;
vector<int>G[MAX];
bool V[MAX];
void dfs(int u){
	V[u]=true;
	for(int i=0;i<G[u].size();i++){
		int v=G[u][i];
		if(!V[v])
			dfs(v);
	}
	out.push_front(u);
}
int main(){
	int u,v,M;
	cin>>N>>M;
	for(int i=0;i<N;i++){
		V[i]=false;
	}
	for(int i=0;i<M;i++){
		cin>>u>>v;
		G[u].push_back(v);
	}
	for(int i=0;i<N;i++){
		if(!V[i])
			dfs(i);
	}
	for(list<int>::iterator it = out.begin();it!=out.end();it++){
		cout<<*it<<endl;
	}
	return 0;
} 

考察:用深度、广度优先搜索实现的拓扑排序算法复杂度同为O(|V|+|E|)。考虑到大规模图容易引起栈溢出,因此不涉及广度搜索更为合适。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值