【问题标题】:why PriorityQueue used in Dijkstra's Algorithm?为什么在 Dijkstra 算法中使用 PriorityQueue?
【发布时间】:2020-08-02 12:39:39
【问题描述】:

我一直在尝试了解 Dijkstra 算法的内部原理,以找到加权图的最短路径。

访问一个顶点后,为什么我们要把相邻的顶点存储到一个PriorityQueue而不是普通的Queue?

我问上述问题的原因是: 我了解 PriorityQueue 我们可以从队列中获取最大/最小数字。但是在 Dijkstra 算法的情况下,我们无论如何都会访问所有顶点,而不管距离/优先级如何。在这种情况下,为什么我们需要使用复杂度为 O(log N) 的 PriorityQueue,而普通队列会做 O(1)?

我错过了什么吗?

【问题讨论】:

    标签: algorithm data-structures priority-queue shortest-path dijkstra


    【解决方案1】:

    Dijkstra 算法(以及 BFS)的要点是,当一个节点离开优先级队列(或 BFS 中的 FIFO 队列)时,它应该与源节点的距离最短,并且距离将被锁定。这些节点将被标记为已访问,并且永远不会再次进入队列。这就是为什么 FIFO 队列在 BFS 中可以正常工作的原因,因为每条边的权重是相等的,并且与源的最短距离将是“跳数”的最小数量。

    现在让我们考虑这个加权图:

           (s)
           / \
         2/   |
         /    |
       (a)    |
        |     |
       3|     |
        |     |
       (b)    |100
        |     |
       2|     |
        |     |
       (c)    |
        \     |
        4\    |
          \  /
          (d)
    

    让我们尝试一个 FIFO 队列来找到节点 s 的最短路径。

           Push s:           Queue: [s],    Distance: s:0
    Pop s, Push a, d:        Queue: [a, d], Distance: s:0, a:2, d:100
    Pop a, Push b:           Queue: [d, b], Distance: s:0, a:2, d:100, b:5
    Pop d, Push c:           Queue: [b, c], Distance: s:0, a:2, d:100, b:5, c:104
    Pop b, No new neighbors, Queue: [c],    Distance: s:0, a:2, d:100, b:5, c:104
    Pop c, No new neighbors, Queue: [],     Distance: s:0, a:2, d:100, b:5, c:104
    

    显然对于节点 c 和 d 来说是错误的,其中最短距离是 7 和 11。使用优先级队列肯定会正确。

    【讨论】:

      【解决方案2】:

      可以通过多种方式到达顶点,使用优先级队列可确保我们在访问顶点时找到到该顶点的最短距离。

      考虑下图:

       a
       |\
      1| \3
       |  \
       c---b
         1  \
             \
             ...
      

      当我们访问顶点a时,我们会将顶点b和顶点c分别放入距离为3和1的优先级队列中。如果我们不使用优先级队列,我们​​可能会首先访问b,这是一个问题,因为我们目前知道的到b 的最短距离是次优的。

      如果我们使用优先级队列,我们​​可以证明当我们探索一个顶点时,没有比我们当前知道的距离更短的到达该顶点的路径。为了矛盾起见,假设我们访问顶点b,当它有更短的路径时。让(u, v) 成为到b 的较短路径上的一条边,这样u 已经被访问过,而v 还没有被访问过。既然u已经被访问过,我们肯定已经将v添加到队列中,并且由于v在到b的较短路径上,它的距离必须小于到b的距离,这意味着它必须在b 之前访问过。因此,我们有一个矛盾,我们知道不可能存在更短的路径。

      【讨论】:

      • 即使在给定的示例中,我们也必须访问所有顶点才能得出从源到目的地的最短路径对吗?那为什么要优先排队呢?
      • @user3470629 不。我们可以在访问目标顶点时立即停止,因为我们知道在访问顶点时总是有最短路径。即使我们确实访问了所有顶点,仍然需要优先级队列,因为否则我们可能会找到到我们已经访问过的顶点的更短路径,从而需要多次访问顶点。这会增加时间复杂度。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-09-10
      • 1970-01-01
      • 1970-01-01
      • 2012-06-23
      • 2013-11-21
      • 1970-01-01
      • 2012-07-25
      相关资源
      最近更新 更多