WBS任务分解中前置任务闭环回路检测:有向图的简单应用(C#)

时间:2022-06-14 03:24:18

标签:

1 场景描述

系统中用到了进度计划编制功能,支持从project文件直接导入数据,并能够在系统中对wbs任务进行增、删、改操作。wbs任务分解中一个重要的概念就是前置任务,前置任务设置确定了不同任务项之间的依赖关系,以软件开发的一般过程为例,需求调研就是系统设计的前置任务。具体来说前置任务又分为以下四种类型

Finish-to-Start (FS)

把这个任务的开始日期和前提条件任务的结束日期对齐,一般用于串行的任务安排,前一个任务必须完成后才能启动下一个新任务

Start-to-Start (SS)

把这个任务的开始日期和前提条件任务的开始日期对齐,一般用于并行任务的安排,也可以一个任务启动后,第二个任务延后或提前数日启动。

Finish-to-Finish (FF)

把这个任务的结束日期和前提条件任务的结束日期对齐,可以用于协调任务的统一时间完成,这样可以定义好任务的开始时间

Start-to-Finish (SF)

把这个任务的结束日期和前提条件任务的开始日期对齐,或者说是前置任务开始的日期决定了后续任务的完成时间

不管是哪种类型,某项任务总是依赖于其前置任务,这就要求,任务的前置关系不能出现循环(闭环),比如A->B->A这种情况是绝对不允许的。

WBS任务分解中前置任务闭环回路检测:有向图的简单应用(C#)

任务关系表基本数据格式如下

WBS任务分解中前置任务闭环回路检测:有向图的简单应用(C#)

SourceId跟TargetId标识任务的Id,通过SourceId、TargetId确定任务之间前后置关系。每个任务项可以看作是一个节点,任务的前置关系可以标识节点与节点之间有向连线,这在数据结构中是一种标准的有向图。

WBS任务分解中前置任务闭环回路检测:有向图的简单应用(C#)

2 图及图的存储结构 2.1 图的基本概念

先看一下数据结构中对图的定义:图是由有穷、非空点集和边集合组成,简写成G(V,E);

其中G表示Graph,V和E是图中两个基本元素,V表示Vertex(顶点),E表示Edge(边)。图按照边是否有方向又分为有向图和无向图,上面我们看到用箭头表示边方向的是一个有向图,无向图一般用下图方式表示。

WBS任务分解中前置任务闭环回路检测:有向图的简单应用(C#)

本文还涉及到关于图的一个重要概念是

:与某个顶点相连接的边数称为该定点的度

出度、入度:对于有向图的概念,出度表示此顶点为起点的边的数目,入度表示此顶点为终点的边的数目

2.2 图的存储结构

图的存储结构设计有很多种,常用的有邻接矩阵和邻接链表两种。

2.2.1 邻接矩阵

邻接矩阵采用2个数组,一个1维数组用来存储节点信息,一个2维数组用来存储边信息。其中二维数组arr[i][j]表示节点i到j的边信息,如果为1表示有边,如果为0表示无边。

WBS任务分解中前置任务闭环回路检测:有向图的简单应用(C#)

从这个矩阵中,很容易知道图中的信息。
1、可以判断任意两顶点之间是否有边无边
2、要知道某个顶点的度,其实就是这个顶点vi在邻接矩阵中第i行或(第i列)的元素之和
3、求顶点vi的所有邻接点就是将矩阵中第i行元素扫描一遍,arc[i][j]为1就是邻接点

2.2.2 邻接链表

邻接链表总体思路如下:
图中顶点用一个一维数组存储,当然,顶点也可以用单链表来存储,不过,数组可以较容易的读取顶点的信息,更加方便。
图中每个顶点vi的所有邻接点构成一个线性表,由于邻接点的个数不定,所以,用单链表存储,无向图称为顶点vi的边表,有向图则称为顶点vi作为弧尾的出边表。
顶点表的各个结点由data和firstedge两个域表示,data是数据域,存储顶点的信息,firstedge是指针域,指向边表的第一个结点,即此顶点的第一个邻接点。边表结点由adjvex和next两个域组成。adjvex是邻接点域,存储某顶点的邻接点在顶点表中的下标,next则存储指向边表中下一个结点的指针。

WBS任务分解中前置任务闭环回路检测:有向图的简单应用(C#)

关于图的多种存储结构设计方式,请参考数据结构相关数据,慢慢理解。

本文采用邻接链表存储结构实现,对于有向图是否包含闭环的判断,,采用的是拓扑排序方法,如果能够用拓扑排序完成对图中所有节点的排序的话,就说明这个图中没有环,而如果不能完成,则说明有环。

拓扑排序算法的主要操作步骤如下:

1、从有向图中选取一个没有前驱(即入度为0)的顶点,并输出之;

2、从有向图中删去此顶点同时找到该顶点的邻接点,将该顶点的邻接点的入度-1,若入度为0则压入栈中