【问题标题】:How to maintain a reference to a std::priority_queue's container?如何维护对 std::priority_queue 容器的引用?
【发布时间】:2017-07-25 16:13:02
【问题描述】:

我正在使用std::vector 作为容器创建一个std::priority_queue

似乎优先级队列在其构造函数中创建了传递给它的容器的副本,因为在构造队列后对容器所做的更改不会反映在队列的容器中。

例如,如果我在容器上调用 clear(),优先级队列仍然是满的。

有没有办法在构造后维护对优先级队列内部容器的引用?

【问题讨论】:

  • 请注意,您可以从priority_queue 派生,并且您的派生类可以访问容器(我认为它被恰当地称为c)。
  • 谢谢理查德,这就是我现在使用的方法,效果很好。

标签: c++ vector queue containers


【解决方案1】:

不,没有办法做到这一点。原因是,如果您可以访问底层容器,您可以访问它并修改它,就像它不是优先级队列一样,这将非常令人困惑并且违背了std::priority_queue 的所需用例,即提供一个队列。

这是从标准的角度来看的,也许您的实现有一个允许该访问的扩展,但这会非常令人惊讶,而且我知道没有实现这样做。您应该查阅相应的文档以确定。

话虽如此,您始终可以在std::priority_queue 周围提供一个包装器,用于存储容器。但我不推荐它,(如上所述)您可以在没有队列语义的情况下更改它。

【讨论】:

  • 不正确。有一种方法。见下文。
  • @RichardHodges 我不是说没有办法,我是说只有std::priority_queue 没有办法做到这一点(即没有派生,...)跨度>
【解决方案2】:

std::priority_queue 是为数不多的标准容器之一。

它有一个受保护的成员c,它是容器。

您可以从队列中派生并在派生类中使用c

如果您改变容器,请记住它实际上是一个heap,并且在您离开您的方法之前需要对其应用适当的堆函数。

#include <queue>
#include <algorithm>

struct my_special_queue : std::priority_queue<int>
{
    using underlying_queue = std::priority_queue<int>;

    // re-use all constructors
    using underlying_queue::underlying_queue;

    // add a clear method

    void clear()
    {
        underlying_queue::c.clear();
    }

    void remove_all_odd_numbers()
    {
        c.erase(std::remove_if(c.begin(), c.end(), 
                                [](auto&&x) { return (x % 2) == 1; }), 
                                c.end());
        std::make_heap(c.begin(), c.end(), 
                        underlying_queue::comp);
    }

};

int main()
{
    my_special_queue q;

    // standard priority_queue methods
    q.push(1);
    q.push(2);
    q.push(9);
    q.push(6);
    q.push(4);
    q.push(7);

    if (not q.empty()) {
        q.top();
        q.pop();
    }

    // apply our custom functions    
    q.clear();
    q.remove_all_odd_numbers();
}

【讨论】:

  • 这个解决方法很棒。我将其标记为解决方案,因为它是我想做的可行且可行的替代方案。
  • 这并不是真正的解决方法。这是预期的设计。如果标准库允许对容器进行公共访问,那么用户很容易意外破坏堆的完整性。
  • @Tyson 不,这就是我的意思。它是按设计存在的。允许知道自己在做什么的人访问容器,同时拒绝该类的临时用户。
  • @Richard...误解了你的意思并删除了我的其他评论。如果这是预期设计,那么您是正确的,这不是解决方法。
  • @Tyson 很高兴能帮上忙。几年前,当我想有条件地从优先级队列中删除一些项目时,我自己也遇到了这个问题。在我重新阅读文档之前,我被难住了半天。而且我想不惜一切代价避免写我的乏善可陈的优先队列实现。
猜你喜欢
  • 1970-01-01
  • 2021-09-09
  • 2013-07-02
  • 2016-05-13
  • 2017-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多