迪杰斯特拉(Dijkstra)算法

迪杰斯特拉(Dijkstra)算法

August 11, 2024

迪杰斯特拉算法

该算法是典型的最短路径算法,用于计算一个节点到其他节点的最短路径。

主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止。

起源与历史

来自维基百科:

从鹿特丹到格罗宁根的最短路径是什么?实际上,这就是对于任意两座城市之间的最短路问题。解决这个问题实际上大概只花了我20分钟:一天早上,我和我的未婚妻在阿姆斯特丹购物,累了,我们便坐在咖啡馆的露台上喝咖啡,然后我就试了一下能否用一个算法解决最短路问题。正如我所说,这是一个20分钟的发现。不过实际上,我在3年后的1959年才把这个算法发表在论文上。即使现在来看这篇论文的可读性也非常高,这个算法之所以如此优雅,其中一个原因就是我没用笔纸就设计了它。后来我才知道,没用笔纸设计的优点之一是你不得不避免所有可避免的复杂问题。令我惊讶的是,这个算法最终成为我成名的基石之一。

基本思想

先说明:该问题我们使用的思路实际上是 贪心

首先声明问题:我们要求的是节点 A 到其他节点的最短路径。

定义两个集合 S 和 U,S 集合包含已经求出最短路径的点,U 集合包含还未求出最短路径的顶点。

并且对应创建一个数组 M 用于记录节点 A 到其他节点的距离,在遍历过程中需要对该数组进行更新。

初始时,S 中仅包含起始节点 A,然后此时 M 中的值为,从 A 到其他直接相连的节点的距离(不相连的是 ∞ )。

然后从数组 M 中找出 S 最新加入的点 P(最开始的话会是起始点 A)距离最近的点 Q ,将其放入到集合 S 中,然后用直接与 Q 相连且最近的节点 R 的距离更新数组 M(如果此时 A 到 R 的直接相连距离「此时记录在数组中」大于 A 到 Q 的距离加上 Q 到 R 的距离,则更新数组 M 中,关于 A 到 R 的距离的数据)。

然后依次循环上方进行的步骤,直到遍历完成所有的点,此时数组数据就是我们需要的节点 A 到其他节点的最短路径。

逻辑运行图

伪代码实现

函数 Dijkstra(图 G, 源节点 source):
    初始化一个距离数组 distance,长度为图中节点的数量
    对于每个节点 v ∈ G:
        distance[v] = ∞  // 初始化为无穷大
    distance[source] = 0  // 源节点到自身的距离为0

    初始化一个优先队列 Q  // 用于存储待处理的节点
    将源节点 source 加入 Q

    当 Q 不为空:
        u = 从 Q 中提取距离最小的节点  // 选择当前最短路径的节点
        从 Q 中移除 u

        对于每个相邻节点 v ∈ G[u]:  // 遍历 u 的所有邻居
            如果 distance[u] + 权重(u, v) < distance[v]:
                distance[v] = distance[u] + 权重(u, v)  // 更新距离
                将 v 加入 Q  // 如果 v 不在 Q 中,则加入 Q

    返回 distance  // 返回源节点到所有其他节点的最短距离
最后更新于