图的拓扑排序

拓扑排序是对有向无环图(DAG)的顶点进行排序,使得对于每一条有向边uv,都有u在排序序列之前。本文介绍了拓扑排序的概念、如何进行拓扑排序,以及拓扑排序的实现过程和时间复杂度。

算法思想

按照有向图给出的次序关系,将图中顶点排成一个线性序列,对于有向图中没有限定次序关系的顶点,则可以人为加上任意的次序关系,由此所得顶点的线性序列称之为拓扑有序序列。显然对于有回路的有向图得不到拓扑有序序列,因为有回路的话,顶点的先后次序就不确定了。

例如,下图,我们可以人为限定次序:A B C D 或 A C B D
在这里插入图片描述

如何进行拓扑排序?

  1. 从有向图中选取一个没有前驱(没有在它之前活动)的顶点,输出之;
  2. 从有向图中删去此顶点以及所有以它为尾的弧;
  3. 重复上述两步,直至图空,或者图不空但找不到无前驱的顶点为止。
    没有被打印输出的顶点构成回路了。

例如,A C B H G D F E(不唯一)。可以发现图中所有顶点都被打印输出了,证实了这个有向图中不存在回路。
在这里插入图片描述
拓扑排序的第一步,首先找到没有前驱的顶点,那么没有前驱的顶点,它的特征是什么呢?我们在算法里,如何去找没有前驱的顶点呢?
没有前驱的顶点==入度为零的顶点

删掉这个顶点以及它所对应的出度的弧,又该如何实现呢?
删除顶点及它的出弧==弧头顶点的入度-1

拓扑排序实现

在这里插入图片描述
获取各顶点入度的函数:

void FindID(AdjList G, int indegreeIMAX_VERTEX_NUM]){
	int i; 
	ArcNode *p; 
	for(i=0;i<G.vexnum;i++)
		indegree[i]=0; 
	for(i=0;i<G.vexnum;i++){
		p=G.vertexes[i].firstarc;//找邻接点 
		while(p!=NULL){
			indegree[p->adjvex]++; 
			p=p->nextarc;
		}
	}
}

可以将入度为0的点单独存储,将入度为0的点入队。

int TopoSort(AdjList G){
	Queue Q;/*队列存储入度为0*/
	int indegree[MAX_VERTEX_NUM];//存放每个顶点的入度值
	int i,count,k;//count计数,然后和有向图中顶点总数比较
	ArcNode*p;
	FindID(G,indegree);
	InitStack(&S);//初始化队列
	for(i=0;i<G.vexnum;i++)
		if(indegree[i]==0) EnterQueue(&Q,i);//入队
	count=0;
	while(!StackEmpty(S)){
		DeleteQueue(&Q,&i);//一个入度为0的点出队 
		printf("%c",G.vertex[i].data); 
		count++; 
		p=G.vertexes[i].firstarc; 
		while(p!=NULL){
			k=p->adjvex; 
			indegree[k]--; 
			if(indegree[k]==0) EnterQueue(&S,k); 
			p=p->nextarc; 
		}
	}
	if(count<G.vexnum) return(Error);//有向图中有回路 
	else return(Ok);
}
时间复杂度

如果AOV网络有n个顶点,e条边,在拓扑排序的过程中,搜索入度为零的顶点所需的时间是O(n)。在正常情况下,每个顶点进一次栈,出一次栈,所需时间O(n)。每个顶点入度减1的运算共执行了e次。所以总的时间复杂为O(n+e)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值