戴克斯特拉算法

✍ dations ◷ 2025-09-18 07:32:22 #戴克斯特拉算法

戴克斯特拉算法(英语:Dijkstra's algorithm),又称迪杰斯特拉算法、Dijkstra算法,是由荷兰计算机科学家艾兹赫尔·戴克斯特拉在1956年发现的算法,并于3年后在期刊上发表。戴克斯特拉算法使用类似广度优先搜索的方法解决赋权图的单源最短路径问题。

该算法存在很多变体:戴克斯特拉的原始版本仅适用于找到两个顶点之间的最短路径,后来更常见的变体固定了一个顶点作为源结点然后找到该顶点到图中所有其它结点的最短路径,产生一个最短路径树。

该算法解决了图 G = V , E {displaystyle G=langle V,Erangle } 上带权的单源最短路径问题:196–206。具体来说,戴克斯特拉算法设置了一顶点集合 S {displaystyle S} ,在集合 S {displaystyle S} 中所有的顶点与源点 s {displaystyle s} 之间的最终最短路径权值均已确定。算法反复选择最短路径估计最小的点 u V S {displaystyle uin {V-S}} 并将 u {displaystyle u} 加入 S {displaystyle S} 中。该算法常用于路由算法或者作为其他图算法的一个子模块。举例来说,如果图中的顶点表示城市,而边上的权重表示城市间开车行经的距离,该算法可以用来找到两个城市之间的最短路径。

应当注意,绝大多数的戴克斯特拉算法不能有效处理带有负权边的图。

戴克斯特拉算法在计算机科学的人工智能等领域也被称为均一开销搜索,并被认为是最良优先搜索(英语:best-first search)的一个特例。

戴克斯特拉算法通过保留目前为止所找到的每个顶点 v V {displaystyle vin V} s {displaystyle s} v {displaystyle v} 的最短路径来工作。初始时,原点 s {displaystyle s} 的路径权重被赋为 0 (即原点的实际最短路径=0)。同时把所有其他顶点的路径长度设为无穷大,即表示我们不知道任何通向这些顶点的路径。当算法结束时, d {displaystyle d} 中存储的便是从 s {displaystyle s} v {displaystyle v} 的最短路径,或者如果路径不存在的话是无穷大。

松弛操作是戴克斯特拉算法的基础操作:如果存在一条从 u {displaystyle u} v {displaystyle v} 的边,那么从 s {displaystyle s} v {displaystyle v} 的一条新路径是将边 w ( u , v ) E {displaystyle w(u,v)in E} 添加到从 s {displaystyle s} u {displaystyle u} 的路径尾部来拓展一条从 s {displaystyle s} v {displaystyle v} 的路径。这条路径的长度是 d + w ( u , v ) {displaystyle d+w(u,v)} 。如果这个值比目前已知的 d {displaystyle d} 的值要小,那么可以用这个值来替代当前 d {displaystyle d} 中的值。松弛边的操作一直执行到所有的 d {displaystyle d} 都代表从 s {displaystyle s} v {displaystyle v} 的最短路径的长度值。

算法维护两个顶点集合 S {displaystyle S} Q {displaystyle Q} 。集合 S {displaystyle S} 保留所有已知实际最短路径值的顶点,而集合 Q {displaystyle Q} 则保留其他所有顶点。集合 S {displaystyle S} 初始状态为空,而后每一步都有一个顶点从 Q {displaystyle Q} 移动到 S {displaystyle S} 。这个被选择的顶点是 Q {displaystyle Q} 中拥有最小的 d {displaystyle d} 值的顶点。当一个顶点 u {displaystyle u} Q {displaystyle Q} 中转移到了 S {displaystyle S} 中,算法对 u {displaystyle u} 的每条外接边 w ( u , v ) {displaystyle w(u,v)} 进行松弛。

《算法导论》中给出了以下伪代码:该伪代码计算并保留图 G {displaystyle G} 中原点 s {displaystyle s} 到每一顶点 v {displaystyle v} 的最短距离 d {displaystyle d} 。其中,函数 E x t r a c t M i n ( Q ) {displaystyle Extract-Min(Q)} 将顶点集合 Q {displaystyle Q} 中有最小 d {displaystyle d} 值的顶点 u {displaystyle u} Q {displaystyle Q} 中删除并返回 u {displaystyle u}

 1  function Dijkstra(G, w, s) 2   INITIALIZE-SINGLE-SOURCE(G, s)                //实际上的操作是将每个除原点外的顶点的                    d                      {displaystyle d}  置为无穷大,                    d                =        0              {displaystyle d=0}   3                       S                              {displaystyle Sleftarrow emptyset }   4                       Q                s              {displaystyle Qleftarrow s}                                  //                    Q              {displaystyle Q}  是顶点                    V              {displaystyle V}  的一个优先队列,以顶点的最短路径估计排序 5   while(                    Q                              {displaystyle Qnot =emptyset }  ) 6       do                     u                E        X        T        R        A        C        T                M        I        N        (        Q        )              {displaystyle uleftarrow EXTRACT-MIN(Q)}            //选取                    u              {displaystyle u}                      Q              {displaystyle Q}  中最短路径估计最小的顶点 7                           S                S                u              {displaystyle Sleftarrow Scup u}   8       for each vertex v                             A        d        j                      {displaystyle in Adj}   9            do RELAX(u, v, w)            //松弛成功的结点会被加入到队列中

如果我们只对在 s {displaystyle s} t {displaystyle t} 之间查找一条最短路径的话,我们可以在第5或第6行添加条件如果满足 u = t {displaystyle u=t} 的话终止程序。

在肯尼·罗森所著的《离散数学及其应用》中给出了如下的另一份伪代码:

 1 procedure Dijkstra(G:边全为正权的图) 2   {G带有顶点                    a        =                  v                      0                          ,                  v                      1                          ,                  v                      2                          .        .        .              {displaystyle a=v_{0},v_{1},v_{2}...}  和若干边                    w        (                  v                      i                          ,                  v                      j                          )              {displaystyle w(v_{i},v_{j})}  } 3    for                     i        :=        1              {displaystyle i:=1}   to n 4                           D        (                  v                      i                          )        :=                      {displaystyle D(v_{i}):=infty }   5                        D        (        a        )        :=        0              {displaystyle D(a):=0}   6                        S        :=                      {displaystyle S:=emptyset }   7    while                     z                S              {displaystyle znotin S}   8    begin 9                              u        :=              {displaystyle u:=}  不属于                    S              {displaystyle S}                      D        (        u        )              {displaystyle D(u)}  最小的一个顶点 10                            S        :=        S                {        u        }              {displaystyle S:=Scup {u}}   11        for 所有不属于                    S              {displaystyle S}  的顶点                    v              {displaystyle v}   12            if                     D        (        u        )        +        w        (        u        ,        v        )        <        D        (        v        )              {displaystyle D(u)+w(u,v)<D(v)}   then                     D        (        v        )        :=        D        (        u        )        +        w        (        u        ,        v        )              {displaystyle D(v):=D(u)+w(u,v)}   13    end{                    D        (        z        )        =              {displaystyle D(z)=}  从a到z的最短路长度}

时间复杂度

我们可以用大O符号将该算法的运行时间表示为边数 | E | {displaystyle |E|} 和顶点数 | V | {displaystyle |V|} 的函数。

对于任何基于顶点集 Q {displaystyle Q} 的实现,算法的运行时间是 O ( | E | d k Q + | V | e m Q ) {displaystyle O(|E|cdot dk_{Q}+|V|cdot em_{Q})} ,其中 d k Q {displaystyle dk_{Q}} e m Q {displaystyle em_{Q}} 分别表示完成键的降序排列时间和从 Q {displaystyle Q} 中提取最小键值的时间。

对于没有任何优化的戴克斯特拉算法,实际上等价于每次遍历了整个图的所有结点来找到Q中满足条件的元素(即寻找最小的顶点是 O ( | V | ) {displaystyle O(|V|)} 的),此外实际上还需要遍历所有的边一遍,因此算法的复杂度是 O ( | V | 2 + | E | ) {displaystyle O(|V|^{2}+|E|)}

对于边数少于 | V | 2 {displaystyle |V|^{2}} 的稀疏图来说,可以用邻接表来更有效的实现该算法。

可以使用一个二叉堆或者斐波纳契堆用作优先队列来查找最小的顶点( E x t r a c t M i n {displaystyle Extract-Min} )以优化算法。当用到二叉堆的时候,算法所需的时间为 O ( ( | E | + | V | ) log | V | ) {displaystyle O((|E|+|V|)log |V|)} ,斐波纳契堆能提高一些性能,让算法运行时间达到 O ( | E | + | V | log | V | ) {displaystyle O(|E|+|V|log |V|)}

相关

  • 后天免疫后天性免疫(英语:adaptive immunity)也称为获得性免疫、适应性免疫、特异性免疫、专一性防御,是一种经由与特定病原体接触后,产生能识别并针对特定病原体启动的免疫反应。和后天
  • 杰克逊维尔杰克逊维尔(英语:Jacksonville)是美国佛罗里达州人口最多的城市,美国本土面积最大的城市(英语:List of United States cities by area),也是杜瓦尔县的县治。 1968年,杰克逊维尔市与
  • 河乌河乌(学名:),又名帕氏河乌、亚洲河乌、褐河乌,是广泛分布于亚洲的一种河乌属鸟类,在欧洲、非洲北部、印度、中国、东南亚等地都有分布。体长约22厘米,体重87克,是最大的一种河乌。羽
  • 日本内阁总理大臣列表日本内阁总理大臣列表列出日本历任内阁总理大臣。内阁总理大臣(日语:内閣総理大臣〔內閣總理大臣〕/ないかくそうりだいじん  */?)目前是日本的政府首脑,主要职责为领导内阁运
  • 皮埃尔·贝雷戈瓦皮埃尔·欧仁·贝雷戈瓦(Pierre Eugène Bérégovoy,1925年12月23日-1993年5月1日)法国社会党政治家,拥有乌克兰血统。曾任法国总理(1992-1993)。贝雷戈瓦祖上是在俄罗斯内战离开
  • 玛丽昂·内斯特尔玛丽昂·内斯特尔(Marion Nestle), 哲学博士, 是一名在纽约大学获得波莱特·戈达德荣誉奖的营养学教授。她在1988年到2003年期间在纽约大学营养学担任主席。她在加州大学伯
  • 克里斯蒂娜·涅斯特林格克里斯蒂娜·涅斯特林格(德语:Christine Nöstlinger,1936年10月13日-2018年6月28日),奥地利儿童文学作家,1984年国际安徒生作家奖得主。1936年出生于维也纳的一个工人阶级家庭,父亲
  • 2018年亚洲残疾人运动会2018年第三届亚洲残疾人运动会于2018年10月6日至13日在印度尼西亚雅加达举行。本届亚洲残疾人运动会会徽结合2018年第十八届亚洲运动会的口号“亚洲的能力”(The Energy of A
  • 林滕贝克河坐标:51°14′14″N 7°5′35″E / 51.23722°N 7.09306°E / 51.23722; 7.09306林滕贝克河(德语:Lüntenbeck),是德国的河流,位于该国西部,处于北莱茵-威斯特法伦州,属于伍珀河的支
  • 无线千兆联盟无线千兆联盟(英语:Wireless Gigabit Alliance,缩写为WiGig)是一个商业与工业组织,致力于推动在无需执照的60GHz频带上运行数千兆比特(multi-gigabit)速度的无线设备资料传输技术。