如果我有结构的STL priority_queue,其中优先级基于结构的某个属性,并且我更改其中一个结构的属性,以便新顺序不同,优先级队列是否知道要求本身?或者我是否必须将其从队列中删除并再次推入?我在某处读到了在调用push()和pop()时完成排序,但我想确定。
答案 0 :(得分:1)
没有办法做你所描述的。
将项目推送到优先级队列有三种方法:
push()
(这意味着移动或复制项目,而不是参考)emplace()
(这意味着在队列中创建一个新项目,但无法获得对它的引用) 访问元素的唯一方法是通过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。