最短路径问题—Dijkstra算法和Floyd算法

目录

一、Dijkstra算法求单源最短路径问题 

基本思想

实现细节

算法步骤

算法分析

二、Floyd算法求各顶点之间最短路径问题

基本思想

算法步骤

算法分析 

三、Dijkstra算法和Floyd算法对比


最短路径问题的引出:

最短路径问题一般分为两类:一是单源最短路径,即求图中某一顶点到其他顶点的最短路径,可通过Dijkstra(迪杰斯特拉)算法求解;二是求每一对顶点间的最短路径,可通过Floyd( 弗洛伊德)算法求解。

这里讨论的最短路径问题主要是针对带权有向图而言的,当然也可以认为带权无向图是顶点间有对称弧的带权有向图,无权图的边的权默认为1。我们把带权有向图问题解决了,这些特殊问题也能解决。

称路径上的第一个顶点为源点,最后一个顶点为终点

一、Dijkstra算法求单源最短路径问题 

基本思想

  1. 对于与源点gif.latex?V_%7B0%7D直接相连的顶点,它们之间权值最小的那个边对应的顶点gif.latex?V_%7Bi%7D的最短路径就一定是这条边。(因为不可能通过其他路径从gif.latex?V_%7B0%7Dgif.latex?V_%7Bi%7D 比直接从gif.latex?V_%7B0%7Dgif.latex?V_%7Bi%7D更近了)
  2. 每次确定了到gif.latex?V_%7Bi%7D的顶点的最短路径后,更新未确定的顶点的目前最短路径长度(可通过已经确定的最短路径了),然后我们再选择目前带权路径长度最短的那个未确定的顶点作为我们接下来确定了最短路径长度的新顶点。
  3. 以此类推,共操作n-1次我们求得了源点到其它所有顶点的最短路径长度。

实现细节

  1. dist[]记录从源点到其它各顶点当前的最短路径长度,它的初始状态为:若从gif.latex?V_%7B0%7Dgif.latex?V_%7Bi%7D 有弧,则dist[i]为弧上的权值;否则置dist[i]为无穷。
  2. path[]数组用来表示从源点到顶点i之间的最短路径的前驱顶点。在算法结束时,可以根据其值追溯得到源点 gif.latex?V_%7B0%7Dgif.latex?V_%7Bi%7D的最短路径。
  3. 设置一个集合S记录已求得的最短路径的顶点,初始时把源点gif.latex?V_%7B0%7D放入集合S中。
  4. 集合S每并入一个新顶点gif.latex?V_%7Bi%7D,都要修改源点gif.latex?V_%7B0%7D 到集合(V-S) “V减去S”,中的顶点的当前的最短路径长度值。

算法步骤

  1. 初始化:假设顶点0为源点,集合S初始化为{0},dist[]的初始值dist[i]=arcs[0][i]。
  2. 从顶点集合V-S中选出 gif.latex?V_%7Bi%7D,满足dist[i]=Min{dist[i] |  gif.latex?V_%7Bi%7D∈V-S}, gif.latex?V_%7Bi%7D就是当前求得的一条从gif.latex?V_%7B0%7D出发的最短路径的终点,令S=S∪{i}。
  3. 修改源点gif.latex?V_%7B0%7D 到集合(V-S)中的顶点的当前的最短路径长度值:若dist[i]+arcs[i][k]<dist[k],则更新dist[k]=dist[i]+arcs[i][k],k为集合(V-S)中的任一顶点。

  4. 重复步骤2~3操作共n-1次,直到所有的顶点都包含在S中。

261062e5a9a846ca9afc60eedfa136e0.png

 95730454517547aaa92569462af30b2c.png

算法分析

  • Dijkstra算法很明显是一个贪心策略,一个问题的整体最优解可通过一系列局部的最优解达到,并且每次的选择最优解依赖以前作出的选择,但不依赖后面要作出的选择。
  • 如果我们只需要求源点到某一个特点顶点的最短路径,但这个问题和求解和源点到其它所有顶点的最短路径一样复杂,因为这个问题的最优解依赖于其他问题的最优解,所以时间复杂度也为O(|gif.latex?V%5E%7B2%7D|)。

b65a85bc4862442688f7ff08f50208d7.png

二、Floyd算法求各顶点之间最短路径问题

基本思想

  1. 递推产生一个n阶方阵序列gif.latex?A%5E%7B%28-1%29%7D,gif.latex?A%5E%7B%280%29%7D,...,gif.latex?A%5E%7B%28k%20%29%7D,...,gif.latex?A%5E%7B%28n-1%29%7D,其中gif.latex?A%5E%7B%28k%20%29%7D[i][j]是从顶点Vi到Vj、中间顶点的序号不大于K的最短路径的长度。
  2. Floyd算法是一个迭代的过程,每迭代一次,在从Vi到Vj的路径上就多考虑了一个顶点:经过n次迭代后,所得到的gif.latex?A%5E%7B%28n-1%29%7D[i][j]就是Vi到Vj的最短路径长度,即方阵gif.latex?A%5E%7B%28n-1%29%7D 中就保存了任意一对顶点之间的最短路径长度。

fb400e8c133742bd917ec66cd9e3f08b.png

算法步骤

初始化:方阵gif.latex?A%5E%7B%28-1%29%7D [i][j]=arcs[i][j]

  1. 将V0作为中间顶点,对于所有顶点对{i,j},如果有gif.latex?A%5E%7B%28-1%29%7D[i][j]>gif.latex?A%5E%7B%28-1%29%7D[i][0]+gif.latex?A%5E%7B%28-1%29%7D[0][j] ,则更新 gif.latex?A%5E%7B%28-1%29%7D[i][j]为 gif.latex?A%5E%7B%28-1%29%7D[i][0]+gif.latex?A%5E%7B%28-1%29%7D[0][j]。更新后的方阵标记为gif.latex?A%5E%7B%280%29%7D
  2. 将V1作为中间顶点,继续检测所有顶点对{i,j}。更新后的方阵标记为gif.latex?A%5E%7B%281%29%7D
  3. 将剩余顶点作为中间顶点重复步骤2操作,共操作n次得到的方阵gif.latex?A%5E%7B%28n-1%29%7D就保存了n个顶点中任意一对顶点之间的最短路径长度。

8757f5400fda4ffbafbe3c68511b68ef.png

算法分析 

  • Floyd算法运用到了动态规划(DP)的思想,通过拆分问题,定义问题状态和状态之间的关系,使得问题能够以递推的方式去解决。

25f7c9af16954e949b716dc6ee4f65c5.png

 519890fddeaf4abba098256f7c412360.png

三、Dijkstra算法和Floyd算法对比

693a8edf3a124123b3e64c9a34d23620.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晴落

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值