有向无环图的应用——拓扑排序

目录

一、什么是AOV网?

二、什么是拓扑排序?

2.1 拓扑排序的定义

2.2 拓扑排序的基本思想

三、拓扑排序算法的实现

3.1 算法思想

3.1.1 设置辅助数组indegree[ ]

3.1.2 设置辅助栈

3.1.3 算法思想

3.2 算法实现

3.2.1 求入度

3.2.2 拓扑排序


有向无环图(DAG)是指一个无环路的有向图。有向无环图可用来描述工程或系统的进行过程,如一个工程的施工图、学生课程间的制约关系图等。

一、什么是AOV网?

AOV网:在一个表示工程的有向无环图中,用顶点表示活动,用弧表示活动间的优先关系,称这

样的图为顶点表示活动的网(Activity On Vertex Network),简称为AOV网。 

注意:

  1. AOV网中的弧表示活动之间存在的某种制约关系;
  2. AOV网中不能出现回路,因为自己不能作为自己的先决条件。

下面给出一个AOV网:计算机专业一些必修课程及其先修课程的关系。

 


二、什么是拓扑排序?

2.1 拓扑排序的定义

通过拓扑排序得到的拓扑序列使得AOV网中所有应存在的前驱和后继关系都能得到满足。

 

2.2 拓扑排序的基本思想

  1. 从有向图中选一个无前驱的结点输出;
  2. 将此结点和以它为起点的弧删除;
  3. 重复1、2,直到不存在无前驱的结点;
  4. 若此时输出的结点数小于有向图中的顶点数,则说明有向图存在回路;否则,输出的顶点的顺序即为一个有向无环图的拓扑序列。

下面给出一个例子。

注意:AOV网的拓扑序列不是唯一的。

 


三、拓扑排序算法的实现

3.1 算法思想

3.1.1 设置辅助数组indegree[ ]

indegree[ ]数组用来存放各顶点的入度。于是有:

  1. 找G中无前驱的顶点,即查找indegree[i]为零的顶点 i ;
  2. 删除以 i 为起点的所有弧,即对链在顶点 i 后的所有邻接顶点 k,将对应的indegree[k]减1。

3.1.2 设置辅助栈

为了避免重复检测入度为零的顶点,设置一个辅助栈。若某一顶点的入度减为0,则将它入栈;每当输出某一顶点时,便将它从栈中删除。

3.1.3 算法思想

1、首先求出各顶点的入度,并将入度为0的顶点入栈;

2、只要栈不空,则重复下面的处理:

  • 将栈顶顶点 i 出栈打印;
  • 将顶点 i 的每一个邻接点 k 的入度减1,如果顶点 k 的入度变为0,则将顶点 k 入栈。

 

3.2 算法实现

3.2.1 求入度

void FindID(AdjList *G, int indegree[]) {
    int i;
    ArcNode *p;

    /* 初始化辅助数组indegree[] */
    for (i = 0; i < G->vexnum; ++i)
        indegree[i] = 0;

    /* 求入度 */
    for (i = 0; i < G->vexnum; ++i) {
        p = G->vertex[i].firstarc;
        while (p != NULL) {
            ++indegree[p->adjvex]; /* p->adjvex即顶点i的邻接点 */
            p = p->nextarc;
        }
    }
}

3.2.2 拓扑排序

bool TopoSort(AdjList *G) {
    Stack *S;
    int indegree[MAX_VERTEX_NUM];
    int i, count, k;
    ArcNode *p;

    /* 求入度 */
    FindID(G, indegree);

    /* 初始化辅助栈 */
    InitStack(&S);

    /* 将入度数为0的顶点压入栈中 */
    for (i = 0; i < G->vexnum; ++i)
        if (indegree[i] == 0)
            Push(S, i);
    
    count = 0; /* count用于计算已删除的顶点个数 */
    while (!IsEmpty(S)) {
        Pop(S, &i);
        printf("%s  ", Vertex2Name(G->vertex[i].data));
        ++count;

        /* 更新入度数 */
        p = G->vertex[i].firstarc;
        while (p != NULL) {
            k = p->adjvex;
            --indegree[k];

            /* 判断当前顶点是否满足入栈条件 */
            if (indegree[k] == 0)
                Push(S, k);

            p = p->nextarc;
        }
    }

    ClearStack(S);

    /* false表明该有向图含有回路 */
    return count < G->vexnum ? false : true;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值