1.什么是 Dijkstra 算法(标号法)?

Dijkstra 算法用于在一个带权有向图(通常权值非负)中,从指定的起点出发,求出该起点到图中所有其他顶点的最短路径。

“标号法”这个名字来源于它的操作方式:算法过程中,每个顶点都会被赋予一个标号。

2.实例设定

  • T 标号(Temporary Label,临时标号):表示从起点到该点的暂时的最短路径长度估计值。随着算法进行,T 标号会不断变小(被修正)。
  • P 标号(Permanent Label,永久标号):表示从起点到该点的真正的最短路径长度已经找到了,不再改变。一旦一个顶点获得 P 标号,它就相当于被“确定”了。

假设我们有如下所示的带权有向图,设起点为V1,我们需要求V1到其他所有点的最短路径:

(注意:如果两点之间没有直接连线,可以理解为权重无穷大 ∞)

图的边及权重(邻接关系):

  • V1 → V2 (权重1)
  • V1 → V3 (权重4)
  • V2 → V3 (权重2)
  • V2 → V4 (权重5)
  • V2 → V5 (权重10)
  • V3 → V4 (权重1)
  • V4 → V5 (权重3)

3.算法详细步骤演示

初始状态:

  • 起点V1:设为P标号值为 0。记作P(V1) = 0
  • 其他所有点(V2, V3, V4, V5):全部设为T标号,初始值为
  • 前驱节点:用于记录路径,初始为空。

第1轮迭代:从V1出发

1.修改T标号

我们要检查刚刚获得P标号的点(现在是V1)的所有邻居。 计算方法:T = P + 

  • 邻居V2:
    • 当前T(V2) = ∞
    • 计算新路径:P(V1) + Weight(V1, V2) = 0 + 1 = 1
    • 1 < ∞,所以更新T(V2) = 1
  • 邻居V3:
    • 当前T(V3) = ∞
    • 计算新路径:P(V1) + Weight(V1, V3) = 0 + 4 = 4
    • 4 < ∞,所以更新T(V3) = 4

2.确定P标号

在所有 T 标号中寻找最小值:

  • T(V2) = 1
  • T(V3) = 4
  • T(V4) = ∞
  • T(V5) = ∞

最小值是 1(对应的点是V2)。 所以,将V2T标号改为P标号:P(V2) = 1。 记录路径:V1 → V2

当前状态:P(V1) = 0, P(V2) = 1。其他T(V3) = 4, T(V4) = ∞, T(V5) = ∞

第2轮迭代:从V2出发

1.修改T标号

我们要检查新获得P标号的点(V2)的所有邻居。 注意:V2连接着V3, V4, V5

  • 邻居V3:
    • 当前T(V3) = 4
    • 计算新路径:P(V2) + Weight(V2, V3) = 1 + 2 = 3
    • 3 < 4,我们发现这条路更短,所以更新T(V3) = 3
    • (这意味着路径V1 → V2 → V3V1 → V3更短)
  • 邻居V4:
    • 当前T(V4) = ∞
    • 计算新路径:P(V2) + Weight(V2, V4) = 1 + 5 = 6
    • 6 < ∞,所以更新T(V4) = 6
  • 邻居V5:
    • 当前T(V5) = ∞
    • 计算新路径:P(V2) + Weight(V2, V5) = 1 + 10 = 11
    • 11 < ∞,所以更新T(V5) = 11

2.确定P标号

在所有 T 标号中寻找最小值:

  • T(V3) = 3(刚刚更新的)
  • T(V4) = 6
  • T(V5) = 11

最小值是3(对应的点是V3)。 所以,将V3T标号改为P标号:P(V3) = 3。 记录路径:V1 → V2 → V3

当前状态:P(V1) = 0, P(V2) = 1, P(V3) = 3。其他T(V4) = 6, T(V5) = 11

第3轮迭代:从V3出发

1.修改T标号

检查新获得P标号的点(V3)的所有邻居。 注意:V3连接着V4

  • 邻居V4:
    • 当前T(V4) = 6
    • 计算新路径:P(V3) + Weight(V3, V4) = 3 + 1 = 4
    • 4 < 6,我们发现这条路更短,所以更新T(V4) = 4
    • (这意味着路径V1 → V2 → V3 → V4V1 → V2 → V4更短)

2.确定P标号

在所有 T 标号中寻找最小值:

  • T(V4) = 4(刚刚更新的)
  • T(V5) = 11

最小值是4(对应的点是V4)。 所以,将V4T标号改为P标号:P(V4) = 4。 记录路径:V1 → V2 → V3 → V4

当前状态:P(V1) = 0, P(V2) = 1, P(V3) = 3, P(V4) = 4。其他T(V5) = 11

第4轮迭代:从V4出发

1.修改T标号

检查新获得P标号的点(V4)的所有邻居。 注意:V3连接着V5

  • 邻居V5:
    • 当前T(V5) = 11
    • 计算新路径:P(V4) + Weight(V4, V5) = 4 + 3 = 7
    • 7 < 11,我们发现这条路更短,所以更新T(V5) = 7
    • (这意味着路径V1 → V2 → V3 → V4 → V5V1 → V2 → V5更短)

2.确定P标号

在所有 T 标号中寻找最小值:

  • T(V5) = 7(刚刚更新的)

最小值是7(对应的点是V5)。 所以,将V5T标号改为P标号:P(V5) = 7。 记录路径:V1 → V2 → V3 → V4 → V5

当前状态:所有定点都已获得P标号,算法结束。

4.最终结果汇总

通过上述每步的运算,我们得出了从起点V1到所有其他点的最短路径长度及具体路线:

目标点 最短距离 最短路径
V1 0 V1(起点)
V2 1 V1 → V2
V3 3 V1 → V2 → V3
V4 4 V1 → V2 → V3 → V4
V5 7 V1 → V2 → V3 → V4 → V5

5.总结

如果在考试或做题中遇到此类问题,只需记住以下核心步骤: 1. 选P:在所有 T 标号中选一个最小的,改为 P 标号。 2. 改 T:以这个新 P 点为跳板,看它通向哪里。 -  :  = P +  -  :  < T,则更新邻居的 T 标号。 3. 循环:重复以上两步,直到所有点都变成 P 标号。

这就是 Dijkstra 标号法的全部过程。