简体   繁体   English

Dijkstra的算法-如何使用优先级队列或最小堆?

[英]Dijkstra's algorithm - how could a priority queue or min-heap be used?

I've been struggling implementing Dijkstra's algorithm; 我一直在努力实现Dijkstra的算法; more specifically the part with the priority queue. 更具体地说,具有优先级队列的部分。 To add vertices into a data structure and use an iterator to go through all vertices and find the minimum distance; 将顶点添加到数据结构中,并使用迭代器遍历所有顶点并找到最小距离; that would be easy, but n time. 那很容易,但是n次。

What I want is to: 我想要的是:

  • to be able to insert vertices into the data structure 能够将顶点插入数据结构
  • extract (return and remove) the vertex v with the lowest distance dist[v] 提取(返回并移除)具有最小距离dist [v]的顶点v

I believe that for Dijkstra's algorithm to work properly, you should be able to insert vertices in constant time and extract them in log(n) time; 我相信,为了使Dijkstra的算法正常工作,您应该能够在恒定时间内插入顶点,并在log(n)时间中提取它们; and I've been suggested that priority queues and min-heaps could be used, but to me it doesn't seem realistic that we could keep the queue or min-heaps ordered, because the distances are getting constantly modified. 有人建议我可以使用优先级队列和最小堆,但是对我来说,保持距离或最小堆的排序似乎并不现实,因为距离不断变化。

So how am I supposed to declare and use a priority queue, a min-heap or another data structure to do this? 那么我应该如何声明和使用优先级队列,最小堆或其他数据结构来做到这一点?

You can use a pair to store the node along with the value (the first element should be the value so that the priority queue compares with this value). 您可以使用一对与值一起存储节点(第一个元素应该是该值,以便优先级队列与此值进行比较)。 Maintain a boolean array visit [ ] where you will indicate wheather you have visited or not a certain node (intially all false). 保持布尔数组visit [ ] ,您将在其中指示访问过的站点或未访问的某个节点(基本上全为false)。

Every time you take the front element of the priority queue check if you have visited this node that is check if visit[pq.front().second] == false . 每次当您使用优先级队列的front元素时,都要检查是否visit[pq.front().second] == false了此节点,即visit[pq.front().second] == false Check for all its adjacent edges and add the nodes reached from this path. 检查其所有相邻边并添加从该路径到达的节点。 If it is true then you should ignore it, as you have already visited it with less length. 如果它是真的,那么您应该忽略它,因为您已经访问了较短的时间。 You will not add more than E edges so the time complexity remains the same. 您添加的边不会超过E个,因此时间复杂度保持不变。

You can learn more about this approach in this link http://community.topcoder.com/tc?module=Static&d1=tutorials&d2=standardTemplateLibrary2#priority . 您可以在此链接http://community.topcoder.com/tc?module=Static&d1=tutorials&d2=standardTemplateLibrary2#priority中了解有关此方法的更多信息。

You have basically three choices here: 在这里,您基本上有三个选择:

  1. Use a tree or some other DS that allows you to extract arbitrary number in O(logN) . 使用允许您提取O(logN)任意数字的树或其他DS。 A heap cannot provide this behavior. 堆不能提供此行为。
  2. Maintain an additional DS (could be hash based) that maps map:V->Node Reference - this will allow you to find the desired node efficiently in the heap, and removing a node where you know its position is doable in O(logN) in the heap (the problem is the finding...) 维护一个附加的DS(可能是基于哈希的)来映射map:V->Node Reference这将使您能够在堆中有效地找到所需的节点,并删除一个您知道其位置在O(logN)可行的节点在堆中(问题是发现...)
  3. "Insert anyway", ignore the fact that the heap already contains this node. “无论如何插入”,忽略堆已经包含该节点的事实。 It will cause you to have a larger heap, at size O(n^2) worst case (number of edges), but recall that log(N^2)=2log(N) which is in O(logN) 这将导致您有一个更大的堆,最坏的情况是O(n^2) ,即边数,但请记住, log(N^2)=2log(N)O(logN)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM