k最短路径算法能作为论文中的一个算法嘛
发布网友
发布时间:2022-04-30 15:05
我来回答
共1个回答
热心网友
时间:2022-06-25 22:20
现在,我们准备介绍计算机科学史上伟大的成就之一:Dijkstra最短路径算法[1]。这个算法适用于边的长度均不为负数的有向图,它计算从一个起始顶点到其他所有顶点的最短路径的长度。在正式定义这个问题(3.1节)之后,我们讲解这个算法(3.2节)以及它的正确性证明(3.3节),然后介绍一个简单直接的实现(3.4节)。在第4章中,我们将看到这种算法的一种令人惊叹的快速实现,它充分利用了堆这种数据结构。
3.1 单源最短路径问题
3.1.1 问题定义
Dijkstra算法解决了单源最短路径问题。[2]
问题:单源最短路径
输入:有向图G=(V, E),起始顶点s∈V,并且每条边e∈E的长度e均为非负值。
输出:每个顶点v∈V的dist(s,v)。
注意,dist(s,v)这种记法表示从s到v的最短路径的长度(如果不存在从s到v的路径,dist(s,v)就是+∞)。所谓路径的长度,就是组成这条路径的各条边的长度之和。例如,在一个每条边的长度均为1的图中,路径的长度就是它所包含的边的数量。从顶点v到顶点w的最短路径就是所有从v到w的路径中长度最短的。
例如,如果一个图表示道路网,每条边的长度表示从一端到另一端的预期行车时间,那么单源最短路径问题就成为计算从一个起始顶点到所有可能的目的地的行车时间的问题。
小测验3.1
考虑单源最短路径问题的下面这个输入,起始顶点为s,每个边都有一个标签标识了它的长度:
从s出发到s、v、w和t的最短距离分别是多少?
(a)0,1,2,3
(b)0,1,3,6
(c)0,1,4,6
(d)0,1,4,7
(正确答案和详细解释参见3.1.4节。)
3.1.2 一些前提条件
方便起见,我们假设本章中的输入图是有向图。经过一些微小的戏剧性修改之后,Dijkstra算法同样适用于无向图(可以进行验证)。
另一个前提条件比较重要。问题陈述已经清楚地表明:我们假设每条边的长度是非负的。在许多应用中(例如计算行车路线),边的长度天然就是非负的(除非涉及时光机器),完全不需要担心这个问题。但是,我们要记住,图的路径也可以表示抽象的决策序列。例如,也许我们希望计算涉及购买和销售的金融交易序列的利润。这个问题相当于在一个边的长度可能为正也可能为负的图中寻找最短路径。在边的长度可能为负的应用中,我们不应该使用Dijkstra算法,具体原因可以参考3.3.1节。[3]
3.1.3 为什么不使用宽度优先的搜索
如2.2节所述,宽度优先的搜索的一个“杀手”级应用就是计算从一个起始顶点出发的最短路径。我们为什么需要另一种最短路径算法呢?
记住,宽度优先的搜索计算的是从起始顶点到每个其他顶点的边数最少的路径,这是单源最短路径问题中每条边的长度均为1这种特殊情况。我们在小测验3.1中看到,对于通用的非负长度边,最短路径并不一定是边数最少的路径。最短路径的许多应用,例如计算行车路线或金融交易序列,不可避免地涉及不同长度的边。
但是,读者可能会觉得,通用的最短路径问题与这种特殊情况真的存在这么大的区别吗?如图3.1所示,我们不能把一条更长的边看成3条长度为1的边组成的路径吗?
图3.1 路径
事实上,“一条长度为正整数
的边”和“一条由
条长度为1的边所组成的路径”之间并没有本质的区别。在原则上,我们可以把每条边展开为由多条长度为1的边组成的路径,然后应用宽度优先的搜索对图进行展开来解决单源最短路径问题。
这是把一个问题简化为另一个问题的一个例子。在这个例子中,就是从边的长度为正整数的单源最短路径问题简化为每条边的长度均为1的特殊情况。
这种简化所存在的主要问题是它扩大了图的规模。如果所有边的长度都是小整数,那么这种扩张并不是严重的问题。但在实际应用中,情况并不一定如此。某条边的长度很可能比原图中顶点和边的总数还要大很多!宽度优先的搜索在扩张后的图中的运行效率是线性时间,但这种线性时间并不一定接近原图长度的线性时间。
Dijkstra算法可以看成是在扩张后的图上执行宽度优先的搜索的一种灵活模拟,它只对原始输入图进行操作,其运行时间为近似线性。
关于简化
如果一种能够解决问题B的算法可以方便地经过转换解决问题A,那么问题A就可以简化为问题B。例如,计算数组的中位元素的问题可以简化为对数组进行排序的问题。简化是算法及其*的研究中非常重要的概念,具有极强的实用性。
我们总是应该寻求问题的简化。当我们遇到一个似乎是新的问题时,总是要问自己:这个问题是不是一个我们已经知道怎样解决的问题的伪装版本呢?或者,我们是不是可以把这个问题的通用版本简化为一种特殊情况呢?
3.1.4 小测验3.1的答案
正确答案:(b)。从s到本身的最短路径的长度为0以及从s到v的最短路径的长度为1不需要讨论。顶点w稍微有趣一点。从s到w的其中一条路径是有向边(s,w),它的长度是4。但是,通过更多的边可以减少总长度:路径s→v→w的长度只有1+2=3,它是最短的s−w路径。类似地,从s到t的每条经过两次跳跃的路径的长度为7,而那条更迂回的路径的长度只有1+2+3=6。
3.2 Dijkstra算法
3.2.1 伪码
Dijkstra算法的高层结构与第2章的图搜索算法相似。[4]它的主循环的每次迭代处理一个新的顶点。这个算法的高级之处在于它采用了一种非常“聪明”的规则选择接下来处理哪个顶点:就是尚未处理的顶点中看上去最靠近起始顶点的那一个。下面的优雅伪码精确地描述了这个思路。