算法与数据结构之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}

相关推荐
啦啦啦啦啦zzzz1 小时前
数据结构:哈夫曼编码
数据结构·c++·哈夫曼编码
ChillCoding2 小时前
更新中:C++ STL库,查找排序(基础算法),数据结构,数学算法,竞赛相关基础
数据结构·c++·算法
apcipot_rain3 小时前
计科八股20260606——二叉树、PCA、图深度学习、进程上下文、C语言预编译、文件读写、单精度浮点数
c语言·数据结构·算法·pca·图神经网络
落羽的落羽3 小时前
【项目】JsonRpc框架——开发实现2(业务层)
linux·数据结构·c++·人工智能·算法·json·动态规划
SHARK_pssm3 小时前
【数据结构——单链表】
数据结构·经验分享·笔记
lightqjx3 小时前
【算法】数据结构_并查集
数据结构·算法·并查集
小蒋学算法3 小时前
算法-掉落的方块-线段树
数据结构·算法
Brilliantwxx4 小时前
【算法从零到千】【8-15】滑动窗口
数据结构·算法
Lucis__4 小时前
图的高阶算法:从构造最小生成树到求解最短路径问题
数据结构·c++·算法·图论