每日学习录(数据结构—图)(下)

目录

7.5 最小生成树

7.5.1普里姆(Prim)算法

7.5.2克鲁斯卡尔(Kruskal)算法

7.6最短路径

7.6.1迪杰斯特拉(Dijkstra)算法

7.6.2 弗洛伊德(Floyd)算法

7.7拓扑排序

7.8关键路径


7.5 最小生成树

我们把构造连通网的最小代价生成树称为最小生成树。

找连通网的最小生成树,经典的有两种算法,普里姆算法克鲁斯卡尔算法

7.5.1普里姆(Prim)算法

我们先构造如下图的邻接矩阵。

也就是说,现在我们已经有了一个存储结构为MGragh的G。G有9个顶点,它的arc二维数组如上右图所示。数组中我们用65535来代表∞。

于是普里姆(Prim)算法代码如下,其中INFINITY为权值极大值,不放设65535,MAXVEX为顶点个数最大值,此处大于等于9即可。

7.5.2克鲁斯卡尔(Kruskal)算法

普里姆算法是以某顶点为起点,逐步找各顶点上最小权值的边来构建最小生成树的。我们也可以以边为目标去构建,因为权值是在边上,直接去找最小权值的边来构建生成树也是很自然的想法,只不过构建时要考虑是否会形成环路而已。此时我们就用到了图的存储结构中的边集数组结构。以下是edge边集数组结构的定义代码:

我们将之前的邻接矩阵转化为下右图的边集数组,并且按权值从大到小排序。

于是克鲁斯卡尔(Kruskal)算法代码如下,其中MAXEDGE为边数量的极大值,此处大于等于15即可,MAXVEX为顶点个数最大值,此处大于等于9即可。

对比两个算法,克鲁斯卡尔算法主要是针对边来展开,边数少时效率会非常高,所以对于稀疏图有很大的优势;而普里姆算法对于稠密图,即边数非常多的情况会更好一些。

7.6最短路径

在网图和非网图中,最短路径的含义是不同的。由于非网图它没有边上的权值,所谓的最短路径,其实就是指两顶点之间经过的边数最少的路径;而对于网图来说,最短路径,是指两顶点之间经过的边上权值之和最少的路径,并且我们称路径上的第一个顶点是源点,最后一个顶点是终点。显然,我们研究网图更有实际意义,就地图来说,距离就是两顶点间的权值之和。而非网图完全可以理解为所有的边的权值都为1的网。

这里讲解两种求最短路径的算法。

7.6.1迪杰斯特拉(Dijkstra)算法

时间复杂度为O(n3)。

7.6.2 弗洛伊德(Floyd)算法

求最短路径的显示代码:

该算法的时间复杂度为O(n3),如果面临需要求所有顶点至所有顶点的最短路径问题时,弗洛伊德算法应该是不错的选择。

7.7拓扑排序

在一个表示工程的有向图中,用顶点表示活动,用弧表示活动之间的优先关系,这样的有向图为顶点表示活动的网,我们称为AOV网(Activity On Vertex Network)。

设G=(V,E)是一个具有n个顶点的有向图,V中的顶点序列v1,v2······,vn,满足若从顶点vi到vj有一条路径,则在顶点序列中顶点vi必在顶点vj之前。则我们称这样的顶点序列为一个拓扑序列。

对AOV网进行拓扑排序的基本思路:从AOV网中选择一个入度为0的顶点输出,然后删去此顶点,并删除以此顶点为尾的弧,继续重复此步骤,直到输出全部顶点或者AOV网中不存在入度为0的顶点为止。

首先我们需要确定一下这个图需要使用数据结构。前面求最小生成树和最短路径时,我们用的都是邻接矩阵,但由于拓扑排序的过程中,需要删除顶点,显然用邻接表会更加方便。因此我们需要为AOV网建立一个邻接表。考虑到算法过程中始终要查找入度为0的顶点,我们在原来顶点表结点结构中,增加一个入度域in,结构如下表。

因此对于下图AOV网,我们可以得到下面的邻接表数据结构。

在拓扑排序算法中,涉及的结构代码如下:

在算法中,还需要辅助的数据结构-栈,用来存储处理过程中入度为0的顶点,目的是为了避免每个查找时都要去遍历顶点表找有没有入度为0的顶点。

下面来看看拓扑排序算法代码:

时间复杂度O(n+e)

7.8关键路径

拓扑排序主要是为了解决一个工程能否顺利进行的问题,但有时我们还需要解决工程完成需要的最短时间问题。因此在前面讲的AOV网的基础上,再来介绍一个新的概念。在一个表示工程的带权有向图中,用顶点表示事件,用有向边表示活动,用边上的权值表示活动的持续时间,这种有向图的边表示活动的网,我们称之为AOE网(Activity On Edge Network)。我们把AOE网中没有入边的顶点称之为始点或源点,没有出边的顶点称之为终点或汇点。由于一个工程,总有一个开始,一个结束,所以正常情况下,AOE网只有一个源点一个汇点。

既然AOE网是表示工程流程的,所以它就具有明显的工程的特性。如有在某顶点所代表的事情发生后,从该顶点出发的各活动才能开始。只有在进入某顶点的各活动都已经结束,该顶点所代表的事件才能发生。

尽管AOE网与AOV网都是用来对工程建模的,但它们还是有很大的不同,主要体现在AOV网是顶点表示活动的网,它只描述活动之间的制约关系,而AOE网是用边表示活动的网,边上的权值表示活动持续的时间,如下图对比。因此,AOE网是要建立在活动之间制约关系没有矛盾的基础之上,再来分析完成整个工程至少需要多少时间,或者为缩短完成工程所需时间,应当加快哪些活动等问题。

我们把路径上各活动所持续的时间之和称为路径长度,从源点到汇点具有最大长度的路径叫关键路径,在关键路径上的活动叫关键活动。

现在的问题就是要找出关键路径。

想要找到关键路径,我们只需要找到所有活动的最早开始时间和最晚开始时间,并且比较它们,如果相等就意味着此活动是关键活动,活动间的路径为关键路径。如果不等,则不是。

为此我们需要定义如下几个参数。

1.事件的最早发生时间etv:即顶点vk的最早发生时间。
2.事件的最晚发生时间ltv:即顶点vk的最晚发生时间,也就是每个顶点对应的事件最晚需要开始的    时间,超出此时间将会延误整个工期。
3.活动的最早开工时间ete:即弧ak的最早发生时间。
4.活动的最晚开工时间lte:即弧ak的最晚发生时间,也就是不推迟工期的最晚开工时间。
我们是由1和2可以求得3和4,然后再根据ete[k]是否与lte[k]相等来判断ak是否是关键活动。

求事件的最早发生时间etv的过程,就是我们从头至尾找拓扑序列的过程,因此,在求关键路径前,需要先调用一次拓扑序列算法的代码来计算etv和拓扑序列列表。为此,我们首先在程序开始处声明几个全局变量。

其中stack2用来存储拓扑序列,以便后面求关键路径时使用。

下面是改进过的求拓扑序列算法。

下面来看求关键路径的算法代码:

时间复杂度O(n+e)。

实践证明,通过这样的算法对于工程的前期工期估算和中期的计划调整都有很大的帮助。不过注意,如果是多条关键路径,则单是提高一条关键路径上的关键活动的速度并不能使整个工程缩短工期,而必须提高同时在几条关键路径上的活动速度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值