【问题标题】:Does changing a priority queue element result in resorting the queue?更改优先级队列元素是否会导致重新使用队列?
【发布时间】:2012-12-10 13:42:52
【问题描述】:

我有一个priority_queue,我想修改它的一些内容(优先级值),那么队列会被重新使用吗?

这取决于它是使用 push/pop(更有可能,因为您只需要“插入”,而不是使用整体),还是在访问 top 或 pop 时。

我真的很想更改队列中的一些元素。类似的东西:

priority_queue<int> q;

int a=2,b=3,c=5;
int *ca=&a, *cb=&b, cc=&c;

q.push(a);
q.push(b);
q.push(c); //q is now {2,3,5}

*ca=4;

//what happens to q?
// 1) {3,4,5}
// 2) {4,2,5}
// 3) crash

【问题讨论】:

    标签: c++ stl queue priority-queue


    【解决方案1】:

    priority_queue 复制您推入其中的值。您最后的分配将对优先级队列的顺序以及存储在其中的值产生零影响。

    【讨论】:

    • make_heap 黑客?如果您使用make_heap,然后更改堆中的数据,只要新值保持与旧值相同的顺序,它应该可以正常工作。
    • 如果是int*被压入怎么办,我们使用自定义的比较方法来比较指针指向的int值。
    【解决方案2】:

    很遗憾,std::priority_queue 类不支持您正在寻找的 increase/decrease_key 操作。当然可以在堆中找到要更新的元素,然后调用make_heap 来恢复二进制堆不变量,但这不能像使用std:: 容器/算法那样有效.扫描堆以查找项目是O(N),然后make_heapO(N) 最重要的是 - 对于正确支持更新的二进制堆,应该可以在O(log(N)) 中执行increase/decrease_key

    Boost 提供了set of priority queue implementations,它可能比std::priority_queue(配对堆、斐波那契堆等)更有效,并且还提供可变性,因此您可以有效地执行动态更新。所以总的来说,使用 boost 容器可能是一个更好的选择。

    【讨论】:

      【解决方案3】:

      好的,经过一番搜索,我发现了如何“重新排序”队列,因此在每次更改优先级值后,您需要调用:

      std::make_heap(const_cast<Type**>(&queue.top()),
           const_cast<Type**>(&queue.top()) + queue.size(),
           ComparerClass());
      

      而且队列一定是那么

      std::priority_queue<Type*,vector<Type*>,ComparerClass> queue;
      

      希望这会有所帮助。

      【讨论】:

      • 目前尚不清楚标准是否允许这样做,尽管它似乎适用于一些现有的实现。
      • 仅仅因为您更改了单个元素的优先级而在整个队列上执行make_heap 的总数将是灾难性的低效。它会起作用,但它几乎没有实用价值。
      • 我认为在某些情况下,例如在 Dijkstra 的算法中,可能会重新推送更改后的值
      【解决方案4】:

      我在考虑将优先级队列用于 A* 算法时偶然发现了这个问题。

      基本上,C++ 优先级队列是一个非常有限的玩具。

      动态更改排队元素的优先级需要手动执行底层堆的完整重建,这甚至不能保证在给定的 STL 实现上工作效率极低。
      此外,重建堆需要丑陋的代码,这些代码必须隐藏在另一个混淆的类/模板中。

      至于 C++ 中的许多其他东西,您将不得不重新发明轮子,或者找到任何为您重新发明它的时尚库。

      【讨论】:

        猜你喜欢
        • 2019-09-18
        • 1970-01-01
        • 2012-02-24
        • 1970-01-01
        • 1970-01-01
        • 2014-08-05
        • 2012-03-03
        • 1970-01-01
        • 2010-10-01
        相关资源
        最近更新 更多