📜  DAA-最短路径

📅  最后修改于: 2021-01-12 03:36:12             🧑  作者: Mango


Dijkstra的算法

Dijkstra的算法解决了有向加权图G =(V,E)上的单源最短路径问题,其中所有边均为非负值(即,每个边的w(u,v) ≥0 (u,v )ЄE )。

在以下算法中,我们将使用一个函数Extract-Min() ,该函数提取具有最小密钥的节点。

Algorithm: Dijkstra’s-Algorithm (G, w, s) 
for each vertex v Є G.V  
   v.d := ∞ 
   v.∏ := NIL 
s.d := 0 
S := Ф 
Q := G.V 
while Q ≠ Ф 
   u := Extract-Min (Q) 
   S := S U {u} 
   for each vertex v Є G.adj[u] 
      if v.d > u.d + w(u, v) 
         v.d := u.d + w(u, v) 
         v.∏ := u

分析

该算法的复杂性完全取决于Extract-Min函数。如果使用线性搜索实现提取最小函数,则该算法的复杂度为O(V 2 + E)

在此算法中,如果我们使用min-heap, Extract-Min()函数将其用于从具有最小密钥的Q返回节点,则可以进一步降低该算法的复杂性。

让我们分别将顶点19视为起始顶点和目标顶点。最初,除起始顶点以外的所有顶点都标记为∞,起始顶点则标记为0

Vertex Initial Step1 V1 Step2 V3 Step3 V2 Step4 V4 Step5 V5 Step6 V7 Step7 V8 Step8 V6
1 0 0 0 0 0 0 0 0 0
2 5 4 4 4 4 4 4 4
3 2 2 2 2 2 2 2 2
4 7 7 7 7 7 7
5 11 9 9 9 9 9
6 17 17 16 16
7 11 11 11 11 11 11 11
8 16 13 13 13
9 20

因此,顶点9与顶点1的最小距离为20 。路径是

1→3→7→8→6→9

该路径是根据前驱信息确定的。

路径

贝尔曼福特算法

该算法解决了边权重可能为负的有向图G =(V,E)的单源最短路径问题。此外,如果不存在任何负加权循环,则该算法可用于找到最短路径。

Algorithm: Bellman-Ford-Algorithm (G, w, s) 
for each vertex v Є G.V  
   v.d := ∞ 
   v.∏ := NIL 
s.d := 0 
for i = 1 to |G.V| - 1 
   for each edge (u, v) Є G.E 
      if v.d > u.d + w(u, v) 
         v.d := u.d +w(u, v) 
         v.∏ := u 
for each edge (u, v) Є G.E 
   if v.d > u.d + w(u, v) 
      return FALSE 
return TRUE

分析

第一个for循环用于初始化,运行时间为O(V)次。下一个for循环运行| V-1 |经过边缘,这需要O(E)次。

因此,Bellman-Ford算法运行时间为O(V,E)

下面的示例逐步说明了Bellman-Ford算法的工作原理。该图具有负边缘,但没有任何负周期,因此可以使用此技术解决问题。

在初始化时,除源以外的所有顶点都用∞标记,而源用0标记。

图形

第一步,以最小成本更新可从源到达的所有顶点。因此,顶点ah被更新。

更新

在下一步中,将更新顶点a,b,fe

下一条路

按照相同的逻辑,在此步骤中更新顶点b,f,cg

顶点

在这里,顶点cd被更新。

顶点已更新

因此,顶点s与顶点d之间的最小距离为20

根据先前的信息,路径为s→h→e→g→c→d