拓扑排序及逆拓扑排序

拓扑排序其实就是对有向无环图的顶点的一种排序,每个顶点出现且只出现一次。

对一个AOV网进行拓扑排序的方法:

1、从AOV网中选择一个入度为0的顶点并输出;

2、从网中删除该顶点和所有以它为起点的有向边;

3、重复1和2直到当前的AOV网为空或当前网中不存在入度为0的顶点为止;

1、拓扑排序算法 

该算法中假设使用邻接表作为存储结构:

//拓扑排序
#define Maxsize 100
int indegree[Maxsize];         //存储当前顶点的入度
int print[Maxsize];           //记录拓扑序列
Stack<int> S;                //存储入度为0的顶点

bool TopologicalSort(Graph G)
{
	InitStack(S);           //初始化栈
	for(int i=0;i<G.vexnum;i++)
	{
		if(indegree[i]==0)     //度为0的顶点入栈 
		{
			push(S,i);
		}
	} 
	int count=0;       //计数
	while(!IsEmpty(S))
	{
		pop(S,i);
		print[count++]=i;
		for(p=G.vertices[i].firstarc;p;p=p->nextarc)//将所有i指向的顶点的入度减1,并且将入度减为0的顶点压入栈中 
		{
			v=p->adjvex;
			if(!(--indegree[v]))
			{
				push(S,v)
			}
		}
		if(count<G.vexnum)     //拓扑排序失败,说明有回路 
		{
			return false;
		}
		else
		{
			return true;
		}
			
	} 
 } 

时间复杂度为:O(|V|+|E|);若采用邻接矩阵存储时,其时间复杂度为O(|V|^2);

2、使用DFS进行拓扑排序 

祖先结点的DFS函数结束时间大于子孙结点的DFS函数结束时间,利用DFS求出各顶点结束时间,对于拓扑排序,就是将结束时间从大到小排序。

 //深度优先遍历实现的拓扑排序
 bool visit[Maxnum];      //标记数组,防止顶点被多次访问 
 void DFSTraverse(Graph G)
 {
 	for(int i=0;i<G.vexnum;i++)
 	{
 		visit[i]=false;
	}
	int time=0;       //记录每个顶点调用DFS函数结束时间 
	for(int i=0;i<G.vexnum;i++)
	{
		if(!visit[i])
		DFS(G,i);
	}
  } 
  void DFS(Graph G,int v)
  {
  	visit[v];
  	visit[v]=true;
  	for(w=FirstNeighbor(G,v);w>=0;w=NextNeighbor(G,V,W))  //从顶点v出发,深度优先遍历G
	{
	 	if(!visit[w]);
	 	DFS(G,w);
	} 
	time+=1;
	finishTime[v]=time; 
  } 

3、逆拓扑排序 

逆拓扑排序的步骤:

1、从AOV网中选择一个出度为0的顶点并输出;

2、从网中删除该顶点和所有以它为终点的有向边;

3、重复1和2,直到当前的AOV网为空;

#define Maxsize 100
//拓扑排序
int Dedegree[Maxsize];         //存储当前顶点的出度
int print[Maxsize];           //记录拓扑序列
Stack<int> S;                //存储出度为0的顶点

bool TopologicalSort(Graph G)
{
	InitStack(S);           //初始化栈
	for(int i=0;i<G.vexnum;i++)
	{
		if(Dedegree[i]==0)     //度为0的顶点入栈 
		{
			push(S,i);
		}
	} 
	int count=0;       //计数
	while(!IsEmpty(S))
	{
		pop(S,i);
		print[count++]=i;
		for(p=G.vertices[i].firstarc;p;p=p->nextarc)//将指向i的顶点的出度减1,并且将出度减为0的顶点压入栈中 
		{
			v=p->adjvex;
			if(!(--Dedegree[v]))
			{
				push(S,v)
			}
		}
		if(count<G.vexnum)     //拓扑排序失败,说明有回路 
		{
			return false;
		}
		else
		{
			return true;
		}		
	} 
 } 

4、DFS遍历实现逆拓扑排序 

 //DFS实现的逆拓扑排序
 bool visit[Maxnum];      //标记数组,防止顶点被多次访问 
 void DFSTraverse(Graph G)
 {
 	for(int i=0;i<G.vexnum;i++)
 	{
 		visit[i]=false;
	}
	for(int i=0;i<G.vexnum;i++)
	{
		if(!visit[i])
		DFS(G,i);
	}
  } 
  void DFS(Graph G,int v)
  {
  	visit[v];
  	visit[v]=true;
  	for(w=FirstNeighbor(G,v);w>=0;w=NextNeighbor(G,V,W))  //从顶点v出发,深度优先遍历G
	{
	 	if(!visit[w]);
	 	DFS(G,w);
	} 
	cout<<v;           //输出顶点 
  } 

总结:

1、拓扑排序和逆拓扑排序序列都可能不唯一;

2、若图中有环,则不存在拓扑排序序列或者逆拓扑排序序列; 

  • 14
    点赞
  • 73
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小阿丁呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值