【笔记】AOV网与拓扑排序

来源:互联网 发布:联通网络详单免费流量 编辑:程序博客网 时间:2024/05/16 12:29

  • 无环路有向图
  • AOV网
  • 拓扑排序
  • AOV网的拓扑排序算法实现

1.无环路有向图

  不存在有向环路的有向图称为无环路有向图(简写为dag)。一个无环路有向图对应的无向图可能存在环路,但它不存在有向环路。除非特别声明,有向图中的环路均指有向环路。
  无环路有向图可用于表示偏序集。

2.AOV网

  在每一个工程中,可以将工程分为若干个子工程,这些子工程称为活动。如果用图中的顶点表示活动,以有向图的弧表示活动之间的优先关系,这样的有向图称为AOV网,即顶点表示活动的网。在AOV网中,如果从顶点vi到顶点vj之间存在一条路径<vi,vj>,则顶点vi是顶点vj的直接前驱,顶点vj是顶点vi的直接后继。活动中的制约关系可以通过AOV网中的表示。
  在AOV网中,不允许出现环,如果出现环就表示某个活动是自己的先决条件。因此需要对AOV网判断是否存在环,可以利用有向图的拓扑排序进行判断。


这里写图片描述
这里写图片描述

3.拓扑排序

  拓扑排序就是将AOV网中的所有顶点排列成一个线性序列,并且序列满足以下条件:在AOV网中,如果从顶点vivj存在一条路径,则在该线性序列中,顶点vi一定出现在顶点vj之前。因此拓扑排序的过程就是将AOV网中的各个活动组成一个可行的实施方案。

  对AOV网进行拓扑排序的算法:
  1. 在AOV网中任意选择一个没有前驱的顶点,即顶点入度为零,将该顶点输出。
  2. 从AOV网中删除该顶点,并删除从该顶点出发的弧。
  3. 重复执行步骤1和步骤2,直达AOV网中所有都已经被输出,或者AOV网中不存在无前驱的顶点为止。

  按照上述步骤,AOV网的拓扑序列为(C1,C2,C3,C4,C5,C6,C7,C8,C9,C10)(C6,C7,C8,C9,C1,C2,C3,C4,C5,C10)
  下图是AOV网的拓扑序列的构造过程,其拓扑序列为V1,V2,V3,V5,V4,V6


这里写图片描述

  在对AOV网进行拓扑排序结束后,可能会出现两种情况:一种是AOV网中的顶点全部输出,表示网中不存在回路;另一种是AOV网中还存在没有输出的顶点,剩余的未输出顶点的入度都不为零,表示网中存在回路。

4.AOV网的拓扑排序算法实现

  采用邻接表存储的AOV网的拓扑排序的算法实现:遍历邻接表,将各个顶点入度保存在数组indegree中。将入度为零的顶点入栈,依次将栈顶元素出栈并输出该顶点,对该顶点的邻接顶点的入度减1,如果邻接顶点的入度为零,则入栈;否则,将下一个邻接顶点的入度减1并进行相同的处理。然后继续将栈中元素出栈,重复执行以上过程,直到栈空为止。

int TopologicalSort(AdjGraph N)/*有向图G的拓扑排序。如果图G没有回路,则输出G的一个拓扑序列并返回1,否则返回0*/{    int i,k,count=0;    int indegree[MaxSize];      /*数组indegree存储各顶点的入度*/    SeqStack S;    ArcNode *p;    /*将图中各顶点的入度保存在数组indegree中*/    for(i=0;i<N.vexnum;i++)     /*将数组indegree赋初值*/        indegree[i]=0;    for(i=0;i<N.vexnum;i++)    {        p=N.vertex[i].firstarc;        while(p!=NULL)        {            k=p->adjvex;            indegree[k]++;            p=p->nextarc;        }    }    InitStack(&S);              /*初始化栈S*/    printf("拓扑序列:");    for(i=0;i<N.vexnum;i++)        if(!indegree[i])        /*将入度为零的顶点入栈*/            PushStack(&S,i);        while(!StackEmpty(S))   /*如果栈S不为空*/        {            PopStack(&S,&i);    /*从栈S将顶点j弹出,输出该顶点*/            printf("%s ",N.vertex[i].data);            count++;            /*对入栈T的顶点计数*/            for(p=N.vertex[i].firstarc;p;p=p->nextarc)  /*处理编号为i的顶点的每个邻接点*/            {                k=p->adjvex;            /*顶点序号为k*/                if(--indegree[k]==0)    /*如果k的入度减1后变为0,则将k入栈S*/                    PushStack(&S,k);            }        }        if(count<N.vexnum)        {            printf("该有向网有回路\n");            return 0;        }        else            return 1;}

  对有n个顶点和e条弧的有向图来说,建立求各顶点的入度的时间复杂度为O(e),将零入度的顶点入栈的时间复杂度为O(n);在拓扑排序过程中,若有向图无环,则每个顶点进一次栈,出一次栈,入度减1操作在while语句中总共执行e次,因此拓扑排序总的时间复杂度为O(n+e)