数据结构(20)图的拓扑排序

本文介绍了拓扑排序的概念,它适用于有向无环图(DAG)。拓扑排序能确定流程图的进行顺序,通过寻找并输出入度为零的顶点,直至所有顶点都被输出。文中详细阐述了拓扑排序的实现步骤,包括维护入度计数、使用栈或队列结构,并讨论了如何处理非唯一解的情况。最后,提供了实现拓扑排序的代码概览。
摘要由CSDN通过智能技术生成

数据结构(20)图的拓扑排序

前言

拓扑排序是有向无环图中的应用。所谓有向无环图,顾名思义,首先要求图是有向图,其次要求图中不能有回路,即无环。

使用有向无环图,可以来表示一个流程图,图中的每一条有向边用来表示子工程之间的次序(领先)关系。有时候,我们会关心工程的进行问题,假设子工程A领先于子工程B,这意味着要完成子工程B必须先完成子工程A,因此A必须在B之前进行,否则整个工程就无法顺利进行。

那么,如何得到整个工程的进行顺序呢?对有向无环图进行拓扑排序,将其转化为拓扑序列,就能解决这个问题。

拓扑排序算法的实现

要进行拓扑排序,思路很简单:

  1. 首先,在图中寻找一个入度为零(没有前驱)的顶点,将其输出。

    没有前驱意味着要完成这项子工程不需要先完成其他子工程,因此可以先完成此工程。

  2. 从图中删除掉这个顶点和所有以它为尾的弧

    删除掉这个顶点,意味着该项工程已经完成了,那么以它为前提的工程也就可以开始进行了。

  3. 重复1-2步,直到图中的全部顶点都输出完毕;或者当前的图中,已经不存在没有前驱的顶点了。假如是后一种情况,说明图中存在环。
    img_1
    img_2

  4. 如图所示,首先寻找到入度为0的顶点F,输出F,并且删除掉以它为尾的弧F-D、F-E,修改D、E的入度

  5. 寻找到入度为0的顶点A,输出A,并且删除掉以它为尾的弧A-B、A-C、A-D,修改B、C、D的入度

  6. 寻找到入度为0的顶点C,输出C,并且删除掉以它为尾的弧C-B、C-E,修改B、E的入度

img_3

  1. 寻找到入度为0的顶点B,输出B,无以它为尾的弧

  2. 寻找到入度为0的顶点D,输出D,并且删除掉以它为尾的弧D-E,修改E的入度

  3. 寻找到入度为0的顶点E,输出E,无以它为尾的弧

可以发现,入度为0的顶点不一定唯一,从中随机选择即可;这意味着拓扑排序的结果不一定是唯一的。

这个算法该怎么实现呢?

首先很显然,我们需要维护一个count数组,用于记录每个顶点当前的入度。当某个顶点入度为零时,意味着可以将其输出了。

从图中删除掉这个顶点,可以考虑用一个特殊值(-1)标记该顶点的访问情况,当count[i] == -1时,说明该顶点已经访问过了。而删除掉以它为尾的弧,意味着少了一条边到达本顶点的邻接顶点,也就是说将邻接顶点的入度减一即可。

如果这样设计,我们需要不断遍历count数组,寻找到count[i] == 0的顶点,并且在合适的时候(count数组内所有的值都等于-1时)退出这个循环,可以是可以,总归有些麻烦。

不如转换一下思路,使用栈(或者队列)的结构:首先计算所有顶点的初始入度,然后将count初值为零的顶点全部入栈,再将栈中的顶点依次出栈(出栈的同时修改其所有邻接顶点的入度,若为零则邻接顶点也入栈)。由于有n个顶点,因此出栈的操作应该循环n次;若在少于n次时栈已经空了,说明图中存在回路。

//拓扑排序
void TopologicalSort2(GraphLnk *g){
   
    int n = g->NumVertices;
    
    //创建辅助数组
    int *count = (int *)malloc(sizeof(int)*n);
    assert(count != NULL);
    //初始化辅助数组
    for (int i = 0; i < n; i ++) {
   
        count[i] = 0;
    }
    
    //统计每个顶点的初始入度
    Edge 
  • 19
    点赞
  • 105
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值