STL优先级队列:何时/如何度假?

时间:2012-06-25 21:38:07

标签: c++ stl priority-queue

如果我有结构的STL priority_queue,其中优先级基于结构的某个属性,并且我更改其中一个结构的属性,以便新顺序不同,优先级队列是否知道要求本身?或者我是否必须将其从队列中删除并再次推入?我在某处读到了在调用push()和pop()时完成排序,但我想确定。

3 个答案:

答案 0 :(得分:1)

没有办法做你所描述的。

项目推送到优先级队列有三种方法:

  1. push()(这意味着移动或复制项目,而不是参考)
  2. 构造队列时传递另一个容器或迭代器范围(这也涉及复制或移动,然后在副本上形成堆;不保留对原始文件的引用)
  3. emplace()(这意味着在队列中创建一个新项目,但无法获得对它的引用)
  4. 访问元素的唯一方法是通过top()函数,它返回一个const-reference。

    因此,在推送项目时无法保留对项目的引用,或者获取对队列中已有项目的非const引用。因此,无法直接修改队列项。

    理论上,唯一可以做出影响排序顺序的修改的方法是,队列中的项是否包含指向外部对象的指针,以及排序顺序是否取决于这些外部对象的内容。在这种情况下,您可以显然修改这些外部对象,而队列项仍然指向它们。然后排序顺序将变为无效 - 优先级队列不会更新它,因为它甚至不知道修改。

答案 1 :(得分:1)

priority_queue push()pop()成员函数是根据push_heap()pop_heap()库函数的行为定义的,其中包含完整内容底层容器作为范围传入。

这些函数要求范围(push_heap()上容器中的最后一项除外,因为那是正在添加的项)“应该是有效堆”。如果修改包含的元素使得容器不再是有效堆,那么您将获得未定义的行为。

因此,如果您需要以这种方式修改元素,则需要删除它,修改它,然后再添加它。或者,您可以乱用内容然后调用make_heap()来重建堆。

参见C ++ 11 23.6.4.3“priority_queue members”,25.4.6.1“push_heap”和25.4.6.2“pop_heap”。

答案 2 :(得分:0)

绝对不会以正确的方式重新排序,至少这是不能保证的。 priority_queue的push()和pop()只调用底层堆结构的std :: push_heap()和std :: pop_heap()。

的影响
push(const value_type& x) 

c.push_back(x);
push_heap(c.begin(), c.end(), comp);

根据C ++ 03标准(23.2.3.2.2),其中 c 是队列的基础容器, comp 是排序函数。

push_heap 的一个要求是

  

范围[first,last - 1]应为有效堆。

根据C ++ 03标准的25.3.6.1。

如果修改priority_queue的现有结构,则会破坏堆结构,并且必须使用make_heap将其重新构建为有效的堆结构。

priority_queue也无法知道您是否使用外部引用/指针修改了元素,因为它不会通过调用其中一个方法来通知它。

您应该删除元素并再次添加以实现您想要的效果。您还可以使用一个完全不同的容器,您可以更灵活地删除要删除的元素并再次添加,例如std :: map。