关于Floyd-Warshall,Dijkstra和Bellman-Ford算法之间的区别,我是否正确?


12

我一直在研究这三个,并在下面说明了他们的推论。有人可以告诉我我是否足够正确地理解它们?谢谢。

  1. Dijkstra的算法仅在您只有一个来源并且想知道从一个节点到另一个节点的最小路径时使用,但是在这种情况下会失败

  2. 当所有节点中的任何一个都可以作为源时,将使用Floyd-Warshall算法,因此您希望从任何源节点到任何目标节点的距离最短。仅在出现负循环时失败

(这是最重要的一个。我的意思是,这是我最不确定的一个:)

3,贝尔曼·福特(Bellman-Ford)和迪杰斯特拉(Dijkstra)一样,只有一个来源。它可以处理负数权重,其工作方式与Floyd-Warshall相同,只是有一个来源,对吗?

如果需要看一下,相应的算法是(由维基百科提供):

贝尔曼福特:

 procedure BellmanFord(list vertices, list edges, vertex source)
   // This implementation takes in a graph, represented as lists of vertices
   // and edges, and modifies the vertices so that their distance and
   // predecessor attributes store the shortest paths.

   // Step 1: initialize graph
   for each vertex v in vertices:
       if v is source then v.distance := 0
       else v.distance := infinity
       v.predecessor := null

   // Step 2: relax edges repeatedly
   for i from 1 to size(vertices)-1:
       for each edge uv in edges: // uv is the edge from u to v
           u := uv.source
           v := uv.destination
           if u.distance + uv.weight < v.distance:
               v.distance := u.distance + uv.weight
               v.predecessor := u

   // Step 3: check for negative-weight cycles
   for each edge uv in edges:
       u := uv.source
       v := uv.destination
       if u.distance + uv.weight < v.distance:
           error "Graph contains a negative-weight cycle"

Dijkstra:

 1  function Dijkstra(Graph, source):
 2      for each vertex v in Graph:                                // Initializations
 3          dist[v] := infinity ;                                  // Unknown distance function from 
 4                                                                 // source to v
 5          previous[v] := undefined ;                             // Previous node in optimal path
 6                                                                 // from source
 7      
 8      dist[source] := 0 ;                                        // Distance from source to source
 9      Q := the set of all nodes in Graph ;                       // All nodes in the graph are
10                                                                 // unoptimized - thus are in Q
11      while Q is not empty:                                      // The main loop
12          u := vertex in Q with smallest distance in dist[] ;    // Start node in first case
13          if dist[u] = infinity:
14              break ;                                            // all remaining vertices are
15                                                                 // inaccessible from source
16          
17          remove u from Q ;
18          for each neighbor v of u:                              // where v has not yet been 
19                                                                                 removed from Q.
20              alt := dist[u] + dist_between(u, v) ;
21              if alt < dist[v]:                                  // Relax (u,v,a)
22                  dist[v] := alt ;
23                  previous[v] := u ;
24                  decrease-key v in Q;                           // Reorder v in the Queue
25      return dist;

弗洛伊德·沃希尔(Floyd-Warshall):

 1 /* Assume a function edgeCost(i,j) which returns the cost of the edge from i to j
 2    (infinity if there is none).
 3    Also assume that n is the number of vertices and edgeCost(i,i) = 0
 4 */
 5
 6 int path[][];
 7 /* A 2-dimensional matrix. At each step in the algorithm, path[i][j] is the shortest path
 8    from i to j using intermediate vertices (1..k−1).  Each path[i][j] is initialized to
 9    edgeCost(i,j).
10 */
11
12 procedure FloydWarshall ()
13    for k := 1 to n
14       for i := 1 to n
15          for j := 1 to n
16             path[i][j] = min ( path[i][j], path[i][k]+path[k][j] );

我很确定Dijkstra的算法可以处理负重量节点。如果存在负权重循环,则无论采用哪种算法,最短路径都是不确定的。
凯文·克莱恩

1
@kevincline:Wikipedia不支持您的主张(尽管我不认为Wikipedia是正确的,而且我的AlgTheory书距离我们只有几百英里),但是,在现实中基于时间或基于速度的路由问题中存在没有负面影响,因此我通常根据需要进行Dijsktra或Floyd的测试。据我所知,大多数现实中的制图路由算法都是基于Dijsktra的现代化版本,但是我只是从我在以前工作场所阅读的一些科学论文中就记住了这一点。
Aadaam

@Aadaam:我错了。Dijkstra利用非负性来避免访问每个边缘。
凯文·克莱恩

是的,您理解正确。:)
Sanghyun Lee 2012年

Answers:


3

如果我正确理解您,则您的理解是正确的。

  • Djikstra的查找找到了从源节点到图中每个其他节点的最小成本路径,除非权重边为负。(只要将Dijkstra找到目标节点,然后将其更改为停止并添加启发式方法,就可以轻松地将其转换为A *算法。)
  • Bellman-Ford与Dijkstra的一样,但速度较慢。但它可以处理负重边缘。
  • Floyd-Warshall找到从每个节点到每个其他节点的最小成本路径的成本。(它返回一个数值矩阵。)它比Djikstra或Bellman-Ford都要慢得多。与您编写的内容不同,它不会在出现负循环时失败,它只会向自己报告某个节点的成本毫无意义的负数。

1
不,Floyd-Warshall可以自己计算路径,与Djikstra和Bellman-Ford一样,而不仅仅是路径长度。
康拉德·鲁道夫2012年

当然要进行修改。
Ceasar Bautista 2012年

3
如果它停在目标节点上,但不使用启发式方法,我仍然会认为第一个是Dijkstra。
艾略特·鲍尔

1
@CSA-Floyd Warshall为O(n ^ 3),因此对于如此大的图形大约需要10 ^ 300次操作。假设每个操作花费了普朗克时间,那么到计算完成时,宇宙中常规物质中的所有质子都将衰减,并且仅会留下超大质量的黑洞。我相信可能会并行化内部循环。如果这是真的,那么您可能很幸运在所有始于太阳质量的黑洞消失之前就完成了。
Jules'Apr

1
(假设您每个进程可以使用少于一个原子来构建一个处理节点,并且可以使用可观察的宇宙中的所有原子,也就是说……但是您可能需要所有这些原子来存储数据)
Jules
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.