如何理解迪杰斯特拉算法

news/2024/11/23 4:33:08/

路漫漫其修远兮,吾将上下而求索。
                ——屈原

          迪杰斯特拉算法的动态演示

  在最短路径的求解算法中,迪杰斯特拉(Dijkstra)算法应该是非常出名的,但是对于初学者而言却又很难理解为什么这个算法是对的,找到的就是最短路径。下面博主参考了相关资料,和大家谈谈如何理解迪杰斯特拉算法。

一、松弛(relaxation)

  所谓“松弛”是从国外的文献资料上的单词“relaxation”直译而来的,亦可以翻译成“弛豫”。那么,到底什么是松弛呢?
  我们先来看下面这张图片。

这里写图片描述

  上图中,原来认为顶点 vi vj 的最短路径为虚线所标的路径 vi -> vj 。而当将 vk 这个顶点拉进 vi vj 之间后,发现 dist[i][k]dist[k][j]dist[i][j] ,即从顶点 vi 出发,先经过 vi -> vk 这条路,再经过 vk -> vj 这条路,最后抵达 vj 顶点的路径长度比 vi -> vj 这条路要短,所以放弃原来虚线的那条路,而选择新发现的这条路。
  上述过程就是所谓的“松弛”,即好像将原来“紧绷”的“弦”(路 vi -> vj )通过顶点 vk 将它“拉开”,也就“松了下来”。

二、(最优子结构)从 vi vj 的最短路上所经过的顶点 vk 一定满足 vi vk 的路径为最短路

  标题中所给出的结论是显然的。下面我们通过反证法做一些论证。

这里写图片描述

  假设已知上图中实线所示的路径为 vi vj 的最短路径,而现在又发现 vi vk 之间还存在着另一条比 vi vk 的实线路径还要短的路径,即虚线路径。那么 vi vk 的最短路径就应该是从 vi 出发,经过虚线路径到达 vk ,再沿着实线路径抵达 vj 。这与我们先前的假设矛盾!所以,从 vi vj 的最短路上所经过的顶点 vk 一定满足 vi vk 的路径为最短路。

三、(贪心选择性质)对于无负权环的图 G ,若顶点v所对应的距离为 VU 中顶点在距离表中的最小值,则源点到 v 的最短路已经找到

  上述结论中,V指图 G 中的所有顶点集合,U指已经找到从源点出发至该点的最短路的顶点集合。
  首先介绍距离表。所谓距离表,就是记录当前求得的从源点 vi 到该点的最短路径长度。
  依然利用反证法论述上述结论。
  假如该最小值所对应的顶点 v 的单源最短路径并不是当前求得的路径,那么可以找到另外某个VU的其他顶点 v 通过松弛操作,使得 s v的路径更短。而由于 s v的距离已经比 s v的距离长,那么无法通过松弛操作找到更短的路径。
  但是,上述论述都需要一个前提,就是图中不含负权环

这里写图片描述

四、迪杰斯特拉算法的运行过程

  下面,终于正式进入迪杰斯特拉算法的解释。
  首先,我们需要开两个集合 U VU,其中 V 为图G的所有顶点集合, U 为已经求得从源点vi到该点的最短路径的那些顶点。
  同时我们还要开一个表,来记录当前求得的从源点 vi 到该点的最短路径长度,即距离表。
  初始时,集合 U 中只有源点vi,而 VU 中就是 V{vi} ,表中就是vi到该顶点一步可达路径的距离,若不存在一步可达,就记录为
接着每一次循环都将距离表中最短距离所对应的顶点拉入集合U中,并利用新加入的顶点对 VU 中的顶点依次做松弛,若经过新顶点的路径距离比原来的要小,则更新距离表中的值。
  对于上一步骤的正确性,前文已经给出解释。首先,认为距离表中 VU 集合中的顶点所对应的距离值最小者所对应的顶点,即为最新发现的从源点发出的至一点的最短路径,那么还未找到最短路径的其他顶点的最短路势必要经过这个顶点或者 U 中的其他顶点。
如此的循环下去直到所有顶点都被拉入集合U中为止。
  可以从下面的例子来理解上述过程。

这里写图片描述

  下面,从距离表中找到距离最小的顶点2,然后将2号顶点加入集合 U 中,并且对1号顶点到VU集合中的顶点,通过2号顶点做松弛,将距离表更新。

这里写图片描述

  在距离表中找到最小值30,将对应的4号顶点拉进集合 U ,对集合VU中的顶点再做一次松弛。

这里写图片描述

  在距离表中找到最小值50,将对应的3号顶点拉进集合 U ,对集合VU中的顶点再做一次松弛。

这里写图片描述

  再将5号顶点拉入集合 U 中,由于VU已经为空,不需要再做新的更新。至此,算法结束,从源点至其他各个顶点的最短路径都已经找到。

五、存在的问题

  由于上述更新的过程中,如果发现顶点 vi vj 经过新加入的顶点 vk 所得到的路径长度比原来的更短,就对距离表做修改。只要该顶点当前的距离是 VU 中顶点在表中数值的最小值,就认为该顶点的最短路已经找到,而不会对其再做更新。即认为:距离表中 VU 集合中的顶点所对应的距离值最小者所对应的顶点,即为最新发现的从源点发出的至一点的最短路径。而这个认为并非总是成立。事实上,如果 G 中存在负权环,即存在一个圈,该圈上的权值之和为负值,那么每走一次圈,距离就会减小一些,那么就不存在最小距离之说,因为距离可以达到负无穷大。也就是说,距离表中所谓的“最小值”并非真正的最小值,我们总还是能够找到比起更小的值。那么算法正确性就没了保证。

这里写图片描述

  那么,我们该怎么面对带有负权环的图呢?历史上,Richard Bellman和Lester Ford等人给出了他们的解决方案,称为Bellman-Ford算法,它可以帮助我们判断G中是否存在负权环,同时在负权环不存在的情况下给出单源最短路径。对于该算法,这里不做过多介绍,大家可以去查阅相关资料学习。

参考资料:

[1] 最短路径算法——Dijkstra(迪杰斯特拉)算法分析与实现(C/C++)
[2] 算法(第4版),塞奇威克(Robert Sedgewick)、韦恩(Kevin Wayne)著


http://www.ppmy.cn/news/527553.html

相关文章

算法系列——迪杰斯特拉算法(Dijkstra)

本系列旨在用简单的人话讲解算法,尽可能避免晦涩的定义,读者可以短时间内理解算法原理及应用细节。我在努力! 本篇文章编程语言为Python,供参考。 迪杰斯特拉算法(Dijkstra) 典型最短路径算法。用于计算一…

迪杰特斯拉算法

Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,这个算法我主动学了三遍,第一主动学的时候,是看严蔚敏的《数据结构》,当时应该是学懂了,有点透彻地理解了这个算法,但是没有记录下来,后来就…

迪杰斯特拉算法-(.c)

一、定义 Dijkstra算法(迪杰斯特拉算法)是很有代表性的最短路径算法,用于计算一个结点到其他结点的最短路径。该算法指定一个点(源点)到其余各个结点的最短路径,因此也叫做单源最短路径算法。该算法是由荷…

经典迪杰斯特拉算法

参数说明: n,城市的数量 m,边的数量 maxint,认为定义的一个认为是断路的标志 maxnum一个宏 dist[]纪录其他个点到出发点的距离,程序没有把算法写成函数,而是最简单的流水线执行,以0号城市为出发…

迪杰斯特拉算法详解

1.概述:Dijkstra算法是用来寻找两点之间最短路径的算法,在实际生活中有着很大的作用他的思想就是选定一点然后向后遍历直至所有点到选定点的最短距离全部求处为止。 2.算法思想: (1)初始化:先找处从源点V0到…

江苏python工资一般多少_在「江苏杰士德精密工业有限公司」工作或实习是一种怎样的体验?...

2016年7月校招进去杰士德,2019年8月离职 我不谈企业文化,也不谈老板怎么样,我只谈我知道,我经历的! 杰士德是一个集团公司,子公司有七八家,这个可以去天眼查查一下! 部门大概&…

迪杰斯特拉算法(Dijkstra‘s algorithm)以及示例

迪杰斯特拉算法(Dijkstras algorithm)是一种非常重要且有价值的算法。它被广泛应用于计算图中单源最短路径问题,在交通路线规划、网络路由、作业调度等领域有着广泛的应用。 迪杰斯特拉算法是由荷兰计算机科学家克劳德迪杰斯特拉(Edsger W. D…

迪杰斯特拉算法

Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。 Dijkstra算法能得出最短路径的最优解,但由于它遍历计算的节点很多,…