我正在从竞争性编程的书中读到Dijkstra的算法1.在实施程序中,他们写了这样的东西:
#define pair<int,int> ii;
priority_queue< ii,vector<ii>,greater<ii> > pq ;
如果我们将整数s作为源,则实现显示像这样推送对(成本,源)(节点从1到n编号):
pq.push(ii(0,s)) ;
我的问题是我们正在优先级队列中推送一对成本和节点。但是另外两个参数(即vector和更大)在priority_queue声明中做了什么?
priority_queue< ii,vector<ii>,greater<ii> > pq ;
我尝试声明类似的内容:
priority_queue< ii > pq ;
代码有效(在我试过的那些测试用例上)。
任何人都可以告诉我声明的含义:
priority_queue< ii,vector<ii>,greater<ii> > pq ;
上层声明和
之间有什么区别priority_queue< ii > pq ;
宣言?
答案 0 :(得分:4)
因此模板类的声明是这样的:
template <class T, class Container = vector<T>,
class Compare = less<typename Container::value_type> > class priority_queue;
应该有三个模板参数。第一个,&#34; T&#34;,是元素的类型(在您的情况下为ii)。第二个参数是我所谓的&#34;底层容器&#34;。你看,priority_queue是一个适配器,即它秘密使用其他容器,同时向你展示另一组操作。 (您可能希望在维基百科上查找&#34;适配器模式&#34;。)出于性能考虑,您可以告诉编译器它应该在下面使用哪个容器。可以使用标准库中的类deque
和vector
。有关容器类的要求,请参阅here。
现在,比较器用于定义元素的排序。它可以是函数指针,也可以是括号运算符重载的类。它需要你的元素类型的两个参数,并返回(bool)&#34; true&#34;如果第一个元素应出现在队列中的第二个元素之后。当您想要更改默认顺序或使用某种奇特的方式来订购元素时,它非常有用。
e.g。请参阅下面的一个简单的例子
struct car{
car(double engine_displ):_engine_displ(engine_displ) {}
double _engine_displ;
};
bool cmp_cars(car one, car other){
return one._engine_displ < other._engine_displ;
}
//..somewhere else
std::priority_queue<car, std::vector<car>, cmp_cars> pq;
然后,队列应该保持std::vector
- 按引擎排量分类的汽车。
当模板参数列表中出现类似class Container = vector<T>
的内容时,编译器会在std::vector<T>
为您填写,当您不知道您的基础容器类型是什么时。这就是为什么你可以说priority_queue<ii>
;编译器将其扩展为priority_queue<ii,vector<ii>,less<ii>>
。在您的示例中,本书的作者明确使用greater<ii>
,因此队列应该将最少的元素放在前面。这是有道理的,因为在Dijkstra算法中,您对成本最低的路径感兴趣。 priority_queue<ii>
默认情况下使用less<ii>
,所以现在队列会将前面最大的cose路径放在前面,这没有用。
作为旁注,您可能会发现代码实际上是typedef pair<int,int> ii
。 #define
指令告诉预处理器将每个pair<int,int>
替换为&#34; ii&#34;,这根本没有帮助。 Typedef告诉编译器&#34; ii&#34;表示pait<int,int>
。