【问题标题】:STL Priority Queue: When/How Does Resorting Occur?STL 优先队列:诉诸何时/如何发生?
【发布时间】:2012-06-25 21:38:07
【问题描述】:

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

【问题讨论】:

  • 不!您应该切勿修改priority_queue(或mapset 的键)中值的“优先级”。它不会自行解决。弹出->编辑->推送。
  • 如何修改结构?当您将队列推入时,队列会创建一个副本,之后就不应该有真正的方法来获取对队列中项目的引用。

标签: c++ stl priority-queue


【解决方案1】:

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

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

因此,如果您需要以这种方式修改一个元素,您需要通过删除它、修改它,然后将其添加回来来完成。或者,您可以将内容弄乱,然后调用 make_heap() 来重建堆。

请参阅 C++11 23.6.4.3“priority_queue 成员”、25.4.6.1“push_heap”和 25.4.6.2“pop_heap”。

【讨论】:

    【解决方案2】:

    没有办法按照你的描述去做。

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

    1. push()(这意味着移动或复制项目,而不是引用)
    2. 在构造队列时传递另一个容器或迭代器范围(这还涉及复制或移动,然后在副本上形成堆;不保留对原始的引用)
    3. emplace()(这意味着在队列中创建一个新项目,但无法获得对它的引用)

    访问元素的唯一方法是通过top()函数,它返回一个常量引用。

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

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

    【讨论】:

      【解决方案3】:

      肯定不会以正确的方式重新排序,至少不能保证。 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 是排序函数。 p>

      push_heap 的一个要求是

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

      根据 C++03 标准的 25.3.6.1。

      如果您修改priority_queue 的现有结构,这会破坏堆结构,并且必须使用make_heap 重新制作它才能再次成为有效的堆结构。

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

      您应该删除该元素并再次添加它以达到您想要的效果。您还可以使用完全不同的容器,在其中您可以更灵活地选择要删除和再次添加的元素,例如 std::map。

      【讨论】:

        猜你喜欢
        • 2016-04-13
        • 1970-01-01
        • 2012-07-20
        • 2013-11-01
        • 1970-01-01
        • 1970-01-01
        • 2016-03-10
        • 2013-03-16
        相关资源
        最近更新 更多