算法与数据结构之Dijkstra算法

Dijkstra算法主要用于计算图中一个起始节点到其他所有节点的最短路径即单源最短路径。它的核心思想基于贪心策略,

Dijkstra算法在最短路径问题求解上已被证明最优,本文将基于几个例子和考研真题来彻底讲明白这一算法的基本运作原理。

基本流程

Dijkstra算法的基本流程如下:

看着很复杂,其实不然。整个算法就是在不断地更新和维护visited,dist,prev这三个数组外加一个顶点集合S,共计执行len(V)次。上述流程结束后,dist数组内是从起点到各个顶点的最短距离 ,prev内记录的是每个顶点在最短路径上的前驱, visited则记录当前节点是否被更新过 ,顶点集合S 记录使用过的顶点****,当每个顶点都位于顶点集合内时算法结束。****

算法执行过程

Dijkstra算法的执行次数取决于图中顶点的个数,算法在每一轮结束后都会选取disti中最小值对应的顶点Vi用于下一轮的更新,更新的过程就是将当前顶点加入到路径中探索局部最短距离。

在算法执行过程中,需要不断更新dist,visited,prev三个数组,这三个数组的更新方式如下:

  1. 对于dist数组,disti的值为本轮所选点加入到路径后到Vi的最短距离。
  2. 对于visited数组,visitedi的值为bool型,用来判断点Vi是否被更新过。
  3. 对于Prev数组,previ的值是点vi在最短路径上的前驱节点。

更一般化,disti的取值为:

previ的取值为:

总而言之,在算法执行的某一轮中,如果加入该轮使用的顶点后总路径长度变短,那么disti更新为加入该点后的路径长度,顶点i的前驱节点previ,如果路径长度没有变短(包括没有变化),那么disti的值不需要更新,顶点i的前驱节点previ仍保持原样为

算法初始化

图1

在算法开始前,需要对三个数组以及顶点集合S进行初始化,初始化的方法如下:

  1. disti为起点到点Vi的可达路径所对应的距离,如果不存在这样的路径那么设为∞。
  2. previ为从起点到该点可达路径上的前一个顶点编号(其实就是起点),如果从起点到该点存在一条直达路径比如V0-V1那么prev1=0,如果不存在这样的路径那么设为-1。
  3. Visitedi表示算法在某一轮结束后点vi是否用于更新路径,初始化时显然只有起点V0被用到,故只有Visited0为True。
  4. S内存放的是每一轮更新使用的点,初始化时显然只有起点V0被用到,故S内只有V0

用更通俗易懂的话讲,初始化时:

对于visited数组,除了起点对应的值为True,其他均为False

对于dist数组,只要从起点到第i个顶点可以直达,那么disti为起点到该点的距离,否则为∞

对于prev数组,只要从起点到第i个顶点可以直达,那么previ为起点,否则为-1

初始化时dist数组内具体的取值情况:

  • 对于V0,V0到自身距离为0,dist0=0。
  • 对于V1,V0到V1可以直达,V0->V1这条路上Visted值均为True,dist1=length(V0-V1)=10。
  • 对于V2,V0没有办法直接到达V2,必须经过其他点,而任一路径上其他点的visited值均为False,故dist2=∞。
  • 对于V3,同理,V0没有办法直接到达V2,必须经过其他点,而任一路径上其他点的visited值均为False,故dist3=∞。
  • 对于V4,V0到V4可以直达,V0->V4这条路上除终点外Visted值均为True,dist4=length(V0-V4)=5

具体结果如下表所示:

|---------|----|----|----|----|----|
| | V0 | V1 | V2 | V3 | V4 |
| visited | √ | × | × | × | × |
| dist | 0 | 10 | ∞ | ∞ | 5 |
| prev | -1 | 0 | -1 | -1 | 0 |

点集为:S={V0}

例题

例1,如下图所示,使用Dijkstra算法求解V1到各个顶点的最短距离

前边我们说到使用Dijkstra算法求解单源最短路径时,需要使用到三个数组加一个集合。因此,在求解过程中,我们需要不断在其基础上更新,直到图中所有顶点都位于集合S中。在实际做题时,建议大家使用表格的形式来模拟算法执行过程,这样可以方便直观看到每一步的更新情况。

初始化(表0)

|---------|----|----|----|----|----|
| | V0 | V1 | V2 | V3 | V4 |
| visited | √ | × | × | × | × |
| dist | 0 | 10 | ∞ | ∞ | 5 |
| prev | -1 | 1 | -1 | -1 | 1 |

点集为:S={V0}

第一轮(表1)

从表0所对应的dist数组中,发现顶点V4的dist值最小,故本次使用V4来更新路径。将V4加入到路径中,根据dist的更新规则,此时dist数组内各值的调整情况为:

dist0,V0:V0->V0

dist1,V1::V0->V1 or V0->V4->V1 ?

dist2,V2: ∞ or V0->V4->v2

dist3,V3: or V0->V4->v3

dist4,V4:V0->v4

比一比大小,不难得到dist数组最终的取值如表1所示:

|---------|----|----|----|----|----|
| | V0 | V1 | V2 | V3 | V4 |
| visited | √ | × | × | × | √ |
| dist | 0 | 7 | 14 | 7 | 5 |
| prev | -1 | 4 | 4 | 4 | 1 |

点集为:S={V0,V4}

相关推荐
闪电悠米2 小时前
力扣hot100-56.合并区间-排序详解
数据结构·算法·leetcode·贪心算法·排序算法
yuannl105 小时前
图的存储方式
数据结构
会编程的小孩6 小时前
初识数据类型以及变量定义
数据结构·算法
梅梅绵绵冰6 小时前
数据结构-时间复杂度
数据结构·算法
cpp_25017 小时前
P6625 [省选联考 2020 B 卷] 卡牌游戏
数据结构·c++·算法·前缀和·贪心·洛谷题解·省选
起予者汝也8 小时前
Python 数据结构
开发语言·数据结构·python
Frostnova丶9 小时前
(17)LeetCode 41. 缺失的第一个正数
数据结构·算法·leetcode
程序猿乐锅11 小时前
【数据结构与算法 | 第二篇】 双链表的增删改查
数据结构
牧以南歌〆13 小时前
数据结构<一>顺序表
c语言·数据结构·算法
玖玥拾1 天前
C++ 数据结构 八大基础排序算法专题
数据结构·c++·算法·排序算法