赞
踩
拓扑排序是图中重要的操作之一,在实际中应用很广泛.再AOV网中,不应该出现有向环路,因为有环意味着某项活动以自己作为先决条件,这样就进入了死循环.因此,对给定的AOV网应该首先判定网中是否存在环*.检测的办法就是对有向图进行拓扑排序,拓扑排序是指照有向图给出的次序关系,将图中顶点排成一个线性序列,对于有向图中没有限定次序关系的顶点,则可以人为加上任意的次序关系.由此所得顶点的线性序列称为拓扑有序序列.*
给出有向图G - ( V , E ), 对于V中顶点的线性序列**(v1,v2,…,vk)**,如果满足如下条件: 若在 G 中从顶点 vi 到 vj 有一条路径,则在序列中顶点 vi 必须在顶点 vj 之前,称该序列为 G 的一个拓扑序列. 构造有向图的拓扑序列的过程称为拓扑排序.
如果按照拓扑序列中的顶点次序进行每一项活动,就能够保证在每一项活动时,他的所有前驱活动均已完成,从而使整个工程顺序执行.
从拓扑排序步骤可知,若在第三步中,网中所有顶点都被输出,则表明网中无有向环,拓扑排序成功,若按照拓扑排序的顺序开展活动则此工程能顺利完成;若仅输出部分顶点,网中已不存在入度为 0 的顶点,则表明网中有有向环,拓扑排序不成功,则此工程不能顺利完成.
**头结点结构体定义为 : **
typedef struct VexNode{
int innum; //顶点的入度值
VexInfo vex; //顶点的信息
ArcNode *firstarc; //标记第一个 vi 的邻接节点的指针
}VexNode VexList[MaxVerNum];
头结点示意图
innum | vex | firstarc |
---|
此外,我们还需要一个栈来保存拓扑排序过程中入度为 0 的顶点.
void TopologicalOrder(ALGraph G) { InitStack(stack); int count = 0; for( i=0 ;i < G.vexnum ; i++ ) if(VexList[i].innum==0) Push(stack,i); while (!EmptyStack(stack)) { Pop(stack,i); count++; for(p=G.vexs[i].firstarc;p!=NULL;p=p->nextarc) { k=p->adjvex; VexList[k].innum--; if(VexList[k].innum==0) Push(stack,k); } } if(count==G.vexnum) printf("拓扑排序失败,网中存在回路 ."); else printf("拓扑排序成功,网中不存在回路 . "); }
通过上面算法的温习,可以看出 , 对 有 n 个顶点 和 e 条边的有向图来说,求个各顶点入度的时间复杂度为 O(e),建立辅助栈的时间复杂度为O(n).当一个图拓扑排序成功时.所有顶点入度减1 的操作进行了e次.因此拓扑排序的时间复杂度为O(e+n).
有向无环图可以采用深度优先遍历的方法进行拓扑排序.从图中某一顶点出发进行深度优先遍历时最先退出DFS函数的顶点即为出度为 0 的顶点,它是拓扑序列的最后一个顶点.我们用一个临时数组按照先后顺序保存退出DFS函数的顶点,然后逆向输入该数组得到的就是拓扑有序序列.
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。