我们真的需要Dijkstra算法中顶点的“访问或不访问”信息吗?

时间:2015-02-09 13:54:07

标签: algorithm data-structures graph dijkstra shortest-path

Dijkstra's algorithm on Wikipedia (older version, now corrected by me)中,具有优先级队列的实施将在检查较短路径之前检查是否访问过vertex

真的有必要吗?甚至是正确的?

function Dijkstra(Graph, source):
      dist[source] ← 0                      // Initialization
      for each vertex v in Graph:           
          if v ≠ source
              dist[v] ← infinity            // Unknown distance from source to v
              prev[v] ← undefined           // Predecessor of v
          end if
          Q.add_with_priority(v,dist[v])
      end for 


     while Q is not empty:               // The main loop
         u ← Q.extract_min()               // Remove and return best vertex
         mark u as scanned
         for each neighbor v of u:
             if v is not yet scanned: // **is this in need?**
                 alt = dist[u] + length(u, v) 
                 if alt < dist[v]
                     dist[v] ← alt
                     prev[v] ← u
                     Q.decrease_priority(v,alt)
                 end if
             end if
         end for
     end while
     return prev[]

我认为,如果v is scanned already or not的路径需要更新,那么检查v将来会阻止任何机会。


更新

我已经对页面进行了编辑,current Dijkstra's algorithm wiki page现在正确无误。

2 个答案:

答案 0 :(得分:2)

不需要旗帜。只需看看伪代码的这一部分:

if v is not yet scanned:
    alt = dist[u] + length(u, v) 
    if alt < dist[v]
         dist[v] ← alt
         prev[v] ← u
         Q.decrease_priority(v,alt)
    end if
end if

如果你检查不同的部分:

  • alt似乎是一个仅在此处用作临时变量的局部变量,因此写入它并不会在其他任何地方产生任何影响。
  • 如果v已从队列中删除,则其路径最多只要u的路径,否则首先提取u
  • 如果访问了v,则dist[v] <= dist[u] <= alt。在这种情况下,比较alt < dist[v]为false,无论如何都会跳过其余的代码。

只是解释一下,考虑一下优先级队列的作用。它包含按最短已知路径排序的节点。当从队列中提取节点时,所有节点在最远离该节点之前的所有节点以及之后的所有节点将至少与该节点一样远。由于所有较近的节点都已经处理过,所以发现到这些节点之一的任何新路径都将通过至少相距很远的节点。这意味着,来自仍在队列中的节点的提取节点不能有任何更短的路由,因此仅仅检查alt < dist[v]就已经排除了那些被扫描的节点。

答案 1 :(得分:-1)

需要检查V是否已经扫描。

在第一个周期,我们找到顶点(V1),它是源顶点(S1)的邻居顶点的最小代价。

在第二个周期,我们不应该从顶点(V1)反转回源顶点(S1)。

当长度(S1,V1)是邻居成本顶点(V1)的最小值时,反向返回源顶点(S1)。

没有检查V扫描的代码是否会导致某些情况下的循环。