zoukankan      html  css  js  c++  java
  • 数据结构和算法学习笔记十:图的拓扑排序和关键路径

    一.拓扑排序简介

      1.AOV网:在实际的一项工程中,往往会有一个或多个最终的目标,如果我们将这个最终的目标进行拆解,就能拆解出许多中间目标,完成这些目标之间是有先后顺序的.如拍摄一部电影需要首先有剧本有场地有演职人员等,然后进行场景拍摄,最后经过后期制作商业宣传等最终上映.这些中间目标往往是有先后顺序的,我们不可能还没有进行场景拍摄就开始后期制作,不可能没有场地就开始拍摄...如果将这些中间目标或活动使用一张有向图表示出来,使用顶点代表活动,使用弧代表活动之间的先后次序,那么这样一张有向图就可以称为 AOV网(Activity On Vertex Network).AOV网是一张不存在环路的有向图,它一定存在一个或多个出度为0和入度为0的顶点.

      2.拓扑序列:AOV网是一张没有环路的有向图,将其中的部分顶点排成一个序列,序列中任意两个顶点A和B都满足:若从A到B有一条路径,则序列中A一定在B之前,那么这条序列就称为一个拓扑序列.

      3.拓扑排序:对一个有向图构造拓扑序列的过程.

      4.拓扑序列的作用:拓扑序列可以这样理解:如果某个工程中所有活动都必须逐个完成,不能同时做两个活动,那么拓扑序列就是这个工程的所有活动的完成次序.

    二.拓扑排序算法

      拓扑排序的思路是:找到一个入度为0的顶点,找到的入度为0的顶点及以其为尾的弧会被删去,这个顶点被加入拓扑序列中...循环此过程直到所有顶点都被找完.既然要不断寻找入度为0的顶点,那么显然使用邻接表(链表中存储顶点为头的弧)实现图是一个不错的方法,只需在顶点数据结构中增加一个入度域,每次添加一条弧时将对应顶点的入度指针加一,在顶点被删去后遍历其邻接表中的所有弧,每遍历一条弧将相应的顶点的入度域减一即可.

      下面举例说明:

      如图,这是一个电影拍摄的AOV网(参考《大话数据结构》P271的示例图),我们可以对其进行拓扑排序。

        1.入度为0的顶点只有“剧本初步完成”,所以它一定是拓扑序列中的第一个节点,删去这个节点及以其为尾的弧;

        2.入度为0的顶点只有“电影制作启动”,所以它作为拓扑序列中的第二个节点,删去这个节点及以其为为的所有弧;

        3.此时入度为0的顶点有“导演确定”、“前期准备”、“投资确定”共三个,这三个顶点同时放入拓扑序列中作为第三到五个节点,这三个顶点之间的顺序任意,然后删去这些节点及以其为尾的弧;

        4.此时入度为0的顶点有“剧本完善”、“演职人员确定”、“场地确认”共三个,同样放入拓扑序列中并将这些节点删去;

        5.最后依次将“人员到位进驻场地”、“场景拍摄”、“后期制作及上映”三个节点逐个加入拓扑序列中并删去。

        6.注意:将节点加入拓扑序列中是一个节点一个节点加入的,这里为了简便3、4步都直接将三个节点一次性加入,实际上不是这样的,如按照“导演确定”、“剧本完善”、“前期准备”、“演职人员确定”、“投资确定”、“场地确认”这个顺序将节点加入拓扑序列中也是可以的。

    三.关键路径算法

      

      如图所示,现在我们将弧的权值填入(随机填的数值),其中权值代表工期,如“剧本初步完成”到“电影制作启动”的弧权值为1,代表需要1天的时间进行“剧本初步完成”活动,之后才可以开始“电影制作启动”活动。那么我们现在怎么确定整个项目的工期是多少天呢?

      如上图所示,图中每个顶点的下方都添加了一个红色的数字代表最早开始时间,如“剧本初步完成”最早0天开始,因为需要一天的时间进行活动,所以“电影制作启动”最早1天开始,同理,“前期准备”需要“电影制作启动”进行3天时间,所以最早4天时开始...还可以注意到,“场地确认”需要“前期准备”2天和“投资确定”1天后才可以开始,而“投资确定”最早2天时开始,“前期准备”最早4天时开始,所以“场地确认”最早可能3天或6天时开始,显然应该取最大值6天,其他的类似情况同理。最终我们得到了第16天时可以开始“后期制作及上映”活动,所以整个工程的工期是16天。那么另一个问题是所有活动最晚启动的时间怎么得到呢?

      如上图,我们再次使用蓝色字体标出了每个活动的最晚开始时间。最晚开始时间需要使用最后一个活动的最早开始时间进行倒推。“后期制作及上映”最早16天时开始,最晚也应该是16天时开始,倒推回去“场景拍摄”最晚11天开始,因为“场景拍摄”需要进行5天后才能开始“后期制作及上映”。同样地,像“导演确定”活动最晚开始时间推断时会有歧义,因为“剧本完善”最晚8天时开始,而“导演确定”进行2天后就可以开始“剧本完善”了,也就是说“导演确定”最晚可以6天时开始;“演职人员确定”最晚7天时开始,而“导演确定”进行4天后可以开始“演职人员确定”,因此导演确定最晚3天时开始;显然我们应该取6天和3天中的最小值,也就是说最晚3天时开始“导演确定”活动。现在我们可以得到那些工序是有冗余时间的了。

      如上图,我们用橙色数字在弧的下方注明了每一项活动进行的冗余时间,如“投资确定”活动到“场地确认”活动中,投资确定最早2天开始,“场地确认”最晚8天开始,那么开始“场地确认”活动前进行的“投资确定”活动的进行时间最多6天,实际只需要一天,因此有5天的冗余时间。我们可以发现在整个AOE网中有很多活动的冗余时间是0,也就是说这些活动必须准点开始准点结束,它们的任何延期都会影响整个工程的最终完成时间,这些冗余时间为0的路径就可以称为工程的关键路径。

  • 相关阅读:
    python学习笔记-4-列表和元组
    迭代器 生成器, 可迭代对象以及应用场景
    mysql的创创建用户阶段 开启客户端登录和授权阶段
    初识mysql数据库
    拆目录
    日志编码
    数据库mysql的安装.启动和基础配置------windows版本
    协程
    线程锁 死锁现象 递归锁 信号量 条件定时器 队列 线程池
    网络线程
  • 原文地址:https://www.cnblogs.com/movin2333/p/15018153.html
Copyright © 2011-2022 走看看