Dijkstra参观集的目的是什么?

时间:2013-11-10 20:06:27

标签: algorithm dijkstra shortest-path

在Dijkstra算法的维基百科页面上,它们标记了访问过的节点,因此它们不会再次添加到队列中。但是,如果访问了一个节点,那么该节点的距离就越短,那么检查alt < dist[v]是否已经考虑了访问过的节点?我误解了访问集的某些内容吗?

for each neighbor v of u:   
      alt := dist[u] + dist_between(u, v);          // accumulate shortest dist from source
      if alt < dist[v] && !visited[v]:                                 
          dist[v]  := alt;                          // keep the shortest dist from src to v
          previous[v]  := u;
          insert v into Q;                          // Add unvisited v into the Q to be processed
      end if
  end for

2 个答案:

答案 0 :(得分:6)

实际上你需要考虑两套:

  • 访问集
  • 排队集

访问集包含从排队集中弹出的那些顶点。这些不能被重新访问,因为根据定义,已经发现从开始到这些顶点的最短路径

排队集包含按照距起始点最短距离排列的未探测顶点

根据图的density,每个顶点都有可能成为多个边的一部分。 请注意,边是将顶点连接到另一个顶点的最小组件。因此,这意味着可能有多个顶点,边缘到当前顶点。

Dijkstra's algorithm外循环的每次迭代都将顶点(来自排队集)的距离与起始顶点的距离最小,并将边缘成本放宽到连接到它的每个顶点。如果顶点已经在排队集中,则更新队列中的值和位置。

完成alt < dist[v]的原因是因为有可能遇到一个已经在队列中的顶点多次,所以每次遇到它时你必须确保在编辑它到源的距离之前顶点,它的当前距离大于您想要分配给它的新距离(alt < dist[v]),并且它不会被处理为已访问(!visited[v]

  • 根据定义,Dijkstra的算法可以保证一旦节点被标记为visited,该节点的距离值就会最短。 如果某个节点被标记为已访问,则这并不意味着该节点到源的距离与从源到任何其他节点的距离相比是最短距离。 访问意味着Dijkstra算法的目标满足该节点;即它目前存储从源到自身的最小距离。

  • 如果您完全想要放弃对已访问的检查,那么您可以做的是,一旦将节点标记为已访问,您将遍历连接到该节点的所有边缘并删除它们。这可确保处理的任何未来节点没有连接到标记为已访问的任何节点的边。但是,因为图表是使用邻接列表表示的,所以使用此选项在时间上会很昂贵;而且根据图表的密集程度,你最好只有一个访问集 但是,如果您使用邻接矩阵表示图形,那么这样做的好处是检查只需O(N)时间。然而,邻接矩阵使用 N 2 空间vs邻接列表的 N 空间,你将根据内存支付这个价格。或者可能不是很糟糕,具体取决于图表大小。

一旦你理解了这一切,你就会发现代码中所做的一切都需要产生正确的结果。

答案 1 :(得分:4)

是的,你是对的。不需要访问过的矢量。

如果访问了一个节点,那么该节点的距离就越短,因此,正如您所说,检查alt < dist[v]就足够了。

看看这里: