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

Dijkstra's how could a priority queue or min-heap be used?

本文关键字:队列 何使用 优先级 Dijkstra      更新时间:2023-10-16

我一直在努力实现Dijkstra的算法;更具体地说,是优先级队列的部分。将顶点添加到数据结构中,并使用迭代器遍历所有顶点并找到最小距离;这很容易,但是n时间。

我想要的是:

  • 能够将顶点插入数据结构
  • 提取(返回并删除)距离最低的顶点 V[v]

我相信,为了使 Dijkstra 的算法正常工作,您应该能够在常量时间内插入顶点并在 log(n) 时间内提取它们;有人建议可以使用优先级队列和最小堆,但对我来说,我们可以保持队列或最小堆的顺序似乎并不现实,因为距离不断被修改。

那么我应该如何声明和使用优先级队列、最小堆或其他数据结构来做到这一点呢?

您可以使用一对将节点与值一起存储(第一个元素应该是值,以便优先级队列与此值进行比较)。维护一个布尔数组visit [ ],您将在其中指示您访问过或不是某个节点(最初都是假的)。

每次您访问优先级队列的前部元素时,请检查您是否访问过此节点,该节点检查是否visit[pq.front().second] == false 。检查其所有相邻边,并添加从此路径到达的节点。如果这是真的,那么你应该忽略它,因为你已经用更少的长度访问了它。您不会添加超过 E 边,因此时间复杂度保持不变。

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

这里基本上有三个选择:

  1. 使用树或其他一些 DS,允许您提取 O(logN) 中的任意数字。堆无法提供此行为。
  2. 维护一个额外的 DS(可能是基于哈希的)来映射map:V->Node Reference - 这将允许您在堆中有效地找到所需的节点,并删除一个您知道其位置在堆中O(logN)可行的节点(问题是发现......
  3. "仍然插入",忽略堆已包含此节点的事实。这将导致您有一个更大的堆,大小O(n^2)最坏的情况(边缘数),但回想一下log(N^2)=2log(N) O(logN)