优先级队列和 dijkstra

priority queues and dijkstra

提问人:Jonathan Chiou 提问时间:6/8/2013 最后编辑:Adrian PanasiukJonathan Chiou 更新时间:7/7/2013 访问量:2736

问:

向我解释如何构建优先级队列以及为什么您必须以这种方式构建,就好像我对优先级队列的经验的极限是知道队列是什么(我一生中从未使用过队列)。

当我看这个网站时: http://comsci.liu.edu/~jrodriguez/cs631sp08/c++priorityqueue.html

priority_queue<Time, vector<Time>, CompareTime> pq;

我知道时间是为了让你有一个时间队列,比较时间是决定将时间放入队列的优先级的原因,但为什么需要在构造函数中?vector<Time>

关于Dijkstra: 我正在将一个图实现为节点的向量,每个节点都包含该向量中所有相邻位置的列表),所以它看起来像这样:

class Node {
  protected:
  string name;
  int value;
  list<int> nodes
}

我将如何实现 Dijkstra 的这一部分:

for each vertex v in Graph:                                
    dist[v] := infinity ;                               
    previous[v] := undefined ;     

对于 dist[v] = 无穷大,我假设我将每个节点的值设置为无穷大,但是什么变量允许我这样做?对于 previous[v],undefined 是什么意思?

C++

评论

0赞 0x90 6/8/2013
用于 Infinity Checkout 或任何其他未使用的数字/字符串标识符。如果您使用双打 stackoverflow.com/a/8640726/1031417limit.h-1
0赞 Bojin Li 6/8/2013
Vector<Time> 类型可能是为了告诉 STL 优先级队列实现将其 Time 对象存储在 Vector 中,谁知道呢。该网站应该描述为什么会出现这个论点,因为如果没有优先级队列的源代码,它就不明显。

答:

3赞 Nick 6/8/2013 #1

在 C++ 中,int 最大值可以用作无限

#include <limits>

然后使用

int imax = std::numeric_limits<int>::max();

评论

0赞 Jonathan Chiou 6/8/2013
那么如果没有 std::whatever,它会是什么样子呢?最大()?
0赞 jamylak 6/8/2013
@JonathanChiou 将取决于您的系统,但如果是字节,那么它是 ,这就是为什么使用更好,因为您不必猜测int4(1<<31) - 1limits
0赞 Jonathan Chiou 6/8/2013
哦,max 给了我一个整数的最大数字。我需要无穷大,因为我作业中的一个测试用例要求我超过 max()
0赞 Nick 6/8/2013
@JonathanChiou 事实上,在实际场景中,您永远不会有值大于 int 最大值的边
0赞 Jonathan Chiou 6/8/2013
对于 Djikstra 来说,上一行[V] <- undefined 是什么意思?
3赞 Manu343726 6/8/2013 #2

它是一个编程练习(也就是你必须实现everithing),还是一个真正的程序?

如果是最后一个,请签出标准库优先级队列:http://en.cppreference.com/w/cpp/container/priority_queue

另一方面,如果它真的是一个学习练习,经过一番谷歌搜索,你会发现这个:http://pages.cs.wisc.edu/~vernon/cs367/notes/11.PRIORITY-Q.html

我可以写一个介绍/解释priority_queues实现(最大/最小堆、推送/弹出操作等),但那篇论文(我认为)有非常好的例子、解释和图片。

编辑:在看到你对我的问题“这是一个练习还是一个真正的程序?我更愿意在这里写下完整的答案,并举例说明。

STEP1:设置

std::priority_queue有三个模板参数:

  • T:显然,存储在容器中的物品类型。
  • 基础容器:顾名思义,是实现中使用的基础容器的类型。其默认值为 。std::vector<T>
  • Comparer:priority_queue用于比较项目的 Functor 类。它的默认值是 (因此,默认情况下,std::p riority_queue 是最大优先级队列)。 如果你想要一个最小优先级队列(就像你的例子一样,Dijkstra 的算法),你必须通过一个比较器来做到这一点。通常,你为你的类型实现二进制,以使函子工作。std::less<T>operator >std::greater<T>

STEP2:使用std::priority_queue

因此,如果您已经完成了设置,则可以使用。它有三个主要业务:std::priority_queue

  • push():在piority_queue中插入一个值。
  • pop():删除优先级队列的顶部
  • top():返回对存储在priority_queue中的最大(或最小,取决于您的比较器)优先级的元素的常量引用。请注意,top() 不是 remove,它是 pop() 的工作。

例:

#include <queue>
#include <iostream>

//User defined type. For this short example, a simple uint wrapper:
struct Foo
{
    unsigned int i;

    Foo(unsigned int _i) : i(_i) {}
};

//Implementation of operator> for class Foo, to make std::greater<Foo> work:
bool operator>(const Foo& f1 , const Foo& f2)
{
    return f1.i > f2.i;
}

int main()
{
    std::priority_queue<Foo,std::vector<Foo>,std::greater<Foo>> foo_min_priority_queue;

    foo_min_priority_queue.push(Foo(2));
    foo_min_priority_queue.push(Foo(1));
    foo_min_priority_queue.push(Foo(0));

    std::cout << foo_min_priority_queue.top().i << std::endl; //Prints 0 
    foo_priority_queue.pop();

    std::cout << foo_min_priority_queue.top().i << std::endl; //Prints 1 
    foo_min_priority_queue.pop();

    std::cout << foo_min_priority_queue.top().i << std::endl; //Prints 2 
    foo_min_priority_queue.pop();

    return 0;
}

引用:

评论

0赞 Jonathan Chiou 6/8/2013
真正的程序,我需要知道如何使用STL优先级队列
0赞 Manu343726 6/9/2013
@JonathanChiou我用完整的解释和示例编辑了答案。
0赞 Alexei Sholik 7/7/2013
我认为不可能将 STL 的优先级队列用于 Dijkstra 的算法,因为该算法需要对队列进行抽象操作。STL 的优先级队列既不提供此功能,也不提供删除任意元素以更新其优先级并再次插入的能力。为了实现高效的 Dijkstra 算法,斐波那契堆将是一个不错的选择。虽然 d-ary 堆足够简单,可以自己实现(使用数组)。decrease-key
1赞 phoeagon 7/7/2013
@android不是真的。即使队列中存在新元素,您仍然可以将新元素插入到优先级队列中。在实践中,我从未遇到过因此而出现的重大性能下降。
0赞 phoeagon 7/7/2013
而且我不认为比较器是必需的。默认情况下,返回最大值元素,因此您只需要存储距离的否定结果即可。priority_queue