ฉันพูดถูกเกี่ยวกับความแตกต่างระหว่างอัลกอริทึม Floyd-Warshall, Dijkstra และ Bellman-Ford หรือไม่?


12

ฉันกำลังศึกษาทั้งสามและฉันได้ระบุข้อสรุปจากพวกเขาด้านล่าง มีใครบอกฉันได้ไหมว่าฉันเข้าใจถูกต้องเพียงพอหรือไม่ ขอบคุณ.

  1. อัลกอริทึมของ Dijkstra จะใช้เมื่อคุณมีแหล่งเดียวและคุณต้องการทราบเส้นทางที่เล็กที่สุดจากโหนดหนึ่งไปยังอีกโหนดหนึ่ง แต่ล้มเหลวในกรณีเช่นนี้

  2. อัลกอริทึมของ Floyd-Warshall ใช้เมื่อทุกโหนดใด ๆ สามารถเป็นต้นทางดังนั้นคุณต้องการให้ระยะทางที่สั้นที่สุดในการเข้าถึงโหนดปลายทางใด ๆ จากโหนดต้นทางใด ๆ สิ่งนี้จะล้มเหลวก็ต่อเมื่อมีรอบการลบเท่านั้น

(นี่คือสิ่งที่สำคัญที่สุดฉันหมายถึงนี่คือสิ่งที่ฉันแน่ใจน้อยที่สุดเกี่ยวกับ :)

3.Bellman-Ford ใช้เหมือนของ Dijkstra เมื่อมีเพียงแหล่งเดียว สิ่งนี้สามารถรองรับน้ำหนักเชิงลบและการทำงานของมันเหมือนกับของ Floyd-Warshall ยกเว้นแหล่งเดียวใช่ไหม

หากคุณต้องการดูอัลกอริธึมที่เกี่ยวข้องคือ (มารยาท Wikipedia):

ยามฟอร์ด:

 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;

ฟลอยด์-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 ขึ้นอยู่กับความต้องการ เท่าที่ฉันจำได้ algos การจัดเส้นทางการทำแผนที่ในชีวิตจริงส่วนใหญ่นั้นอ้างอิงจาก Dijsktra รุ่นที่ทันสมัย ​​แต่ฉันจำได้จากเอกสารทางวิทยาศาสตร์ที่ฉันได้อ่านจากที่ทำงานก่อนหน้านี้
Aadaam

@Aadaam: ฉันผิด Dijkstra หาช่องโหว่ที่ไม่ใช่การปฏิเสธเพื่อหลีกเลี่ยงการเยี่ยมชมขอบทุกด้าน
วินไคลน์

ใช่คุณเข้าใจถูกต้อง :)
Sanghyun Lee

คำตอบ:


3

ถ้าฉันเข้าใจคุณถูกต้องความเข้าใจของคุณก็ถูกต้อง

  • Djikstra's พบเส้นทางต้นทุนที่เล็กที่สุดจากโหนดต้นทางไปยังโหนดอื่น ๆ ในกราฟยกเว้นว่ามีขอบน้ำหนักเชิงลบ (Dijkstra's สามารถแปลงเป็นอัลกอริทึม A * ได้อย่างง่ายดายโดยเพียงแค่เปลี่ยนเป็นหยุดเมื่อพบโหนดเป้าหมายและเพิ่มการวิเคราะห์พฤติกรรม)
  • Bellman-Ford ทำเช่นเดียวกับ Dijkstra's แต่ช้ากว่า แต่สามารถจัดการกับน้ำหนักที่ติดลบได้
  • Floyd-Warshall ค้นหาค่าเส้นทางที่เล็กที่สุดจากแต่ละโหนดไปยังโหนดอื่น ๆ (ส่งกลับเมทริกซ์ตัวเลข) มันช้ากว่า Djikstra หรือ Bellman-Ford มาก ไม่เหมือนกับสิ่งที่คุณเขียนมันจะไม่ล้มเหลวเมื่อเกิดวัฏจักรลบ แต่จะรายงานตัวเลขลบที่ไม่มีความหมายสำหรับต้นทุนของบางโหนดไปยังตัวมันเอง

1
Nah, Floyd-Warshall สามารถคำนวณเส้นทางได้ด้วยตัวเองเช่นเดียวกับ Djikstra และ Bellman-Ford ไม่ใช่แค่ความยาวเส้นทาง
Konrad Rudolph

ด้วยการดัดแปลงแน่นอน
Ceasar Bautista

3
ฉันจะยังคงพิจารณาคนแรกที่จะเป็น Dijkstra ถ้ามันหยุดที่โหนดเป้าหมาย แต่ไม่ได้ใช้การวิเคราะห์พฤติกรรม
Eliot Ball

1
@CSA - Floyd Warshall คือ O (n ^ 3) ดังนั้นการดำเนินการประมาณ 10 ^ 300 จะต้องใช้สำหรับกราฟขนาดใหญ่เช่นนี้ สมมติว่าการดำเนินการแต่ละครั้งต้องใช้เวลาพลังค์เมื่อถึงเวลาที่การคำนวณเสร็จสิ้นโปรตอนทั้งหมดในสสารปกติในจักรวาลจะสลายตัวและมีเพียงหลุมดำมวลมหาศาลที่เหลืออยู่ ฉันเชื่อว่าอาจเป็นไปได้ที่จะขนานวงใน หากเป็นจริงคุณอาจโชคดีพอที่จะเสร็จสิ้นก่อนหลุมดำทั้งหมดที่เริ่มต้นด้วยมวลของดวงอาทิตย์จะระเหยไป
จูลส์

1
(สมมติว่าคุณสามารถสร้างโหนดการประมวลผลโดยใช้อะตอมน้อยกว่าหนึ่งต่อกระบวนการและสามารถใช้อะตอมทั้งหมดในเอกภพที่สังเกตได้นั่นคือ ... แต่คุณอาจต้องใช้ทั้งหมดในการจัดเก็บข้อมูลของคุณเพื่อเริ่มต้น)
จูลส์
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.