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

时间:2014-02-21 11:22:11

标签: c++ algorithm queue priority-queue dijkstra

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

我想要的是:

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

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

那么我应该如何声明并使用优先级队列,最小堆或其他数据结构来执行此操作?

2 个答案:

答案 0 :(得分:3)

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

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

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

答案 1 :(得分:1)

这里基本上有三种选择:

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