std :: queue iteration

jac*_*hab 67 c++ iteration queue c++-standard-library

我需要迭代std::queue.www.cplusplus.com说:

默认情况下,如果没有为特定队列类指定容器类,则使用标准容器类模板deque.

那么我可以以某种方式到达队列的底层deque并迭代它吗?

CB *_*ley 68

如果你需要遍历a,queue那么你需要的不仅仅是队列.标准容器适配器的要点是提供最小的接口.如果你还需要进行迭代,为什么不使用deque(或列表)呢?

  • 虽然我知道你在说什么,但我总是不喜欢这句话"不仅仅是排队".具有枚举的队列仍然是队列...另外,观察`deque`是如何恰好支持枚举的,完全是任意的.您也可以认为`deque`应该像`queue`一样纯粹,并且不支持迭代,如果你想迭代它,那么你想要"更多"的东西; 例如`deque_enumerable`.虽然这是一个滑坡,我个人的感觉是`队列`应该首先支持枚举. (107认同)
  • @romkyns:如果我改写它会更好:"你需要一些比`queue`接口更丰富的接口,所以你应该选择一个具有合适接口的对象".喜欢与否,迭代不是`queue`接口的一部分,所以如果你想要迭代,你需要选择其他东西. (7认同)
  • 因为我的用例需要一个队列,但我需要将其转储出来以进行调试和记录.假设海报不知道他们在做什么,这通常是没有建设性的. (7认同)
  • @RomanStarkov - 似乎应该可以让`queue`支持前向迭代器,但不能反转迭代器,而不会给我能想到的任何合理的实现带来负担.我猜CS101的教授可能会抱怨它...... (4认同)
  • @EML-完全是我的需要。某种程度上,调试要求常常被忽略,只是流浪疯子所需要的 (3认同)

Ale*_*nov 35

虽然我同意其他人的看法,直接使用可迭代容器是首选解决方案,但我想指出,C++标准可以保证对自己动手解决方案提供足够的支持,以防您出于任何原因需要它.

也就是说,您可以继承std::queue并使用其受保护的成员Container c;来访问底层容器的begin()和end()(前提是存在此类方法).以下示例适用于VS 2010并使用ideone进行测试:

#include <queue>
#include <deque>
#include <iostream>

template<typename T, typename Container=std::deque<T> >
class iterable_queue : public std::queue<T,Container>
{
public:
    typedef typename Container::iterator iterator;
    typedef typename Container::const_iterator const_iterator;

    iterator begin() { return this->c.begin(); }
    iterator end() { return this->c.end(); }
    const_iterator begin() const { return this->c.begin(); }
    const_iterator end() const { return this->c.end(); }
};

int main() {
    iterable_queue<int> int_queue;
    for(int i=0; i<10; ++i)
        int_queue.push(i);
    for(auto it=int_queue.begin(); it!=int_queue.end();++it)
        std::cout << *it << "\n";
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

  • @Deqing:对; 但迭代底层容器不会按优先级顺序排列. (4认同)
  • 所以我们可以对`priority_queue`做同样的事,对吧? (2认同)
  • 为什么重新定义一个新类而不直接使用`deque`?! (2认同)

Stu*_*dMe 10

您可以将原始队列保存到临时队列.然后,您只需在临时队列上执行常规弹出即可通过原始队列,例如:

queue tmp_q = original_q; //copy the original queue to the temporary queue

while (!tmp_q.empty())
{
    q_element = tmp_q.front();
    std::cout << q_element <<"\n";
    tmp_q.pop();
} 
Run Code Online (Sandbox Code Playgroud)

最后,tmp_q将为空,但原始队列未被触及.

  • `std :: queue`似乎没有`.top()`方法 (3认同)

Vae*_*lus 5

虽然Alexey Kukanov 的答案可能更有效,但您也可以以非常自然的方式迭代队列,方法是从队列前面弹出每个元素,然后将其推到后面:

#include <iostream>
#include <queue>

using namespace std;

int main() {
    //populate queue
    queue<int> q;
    for (int i = 0; i < 10; ++i) q.push(i);

    // iterate through queue
    for (size_t i = 0; i < q.size(); ++i) {
        int elem = std::move(q.front());
        q.pop();
        elem *= elem;
        q.push(std::move(elem));
    }

    //print queue
    while (!q.empty()) {
        cout << q.front() << ' ';
        q.pop();
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

0 1 4 9 16 25 36 49 64 81 
Run Code Online (Sandbox Code Playgroud)


小智 5

一种间接的解决方案是使用 std::deque 代替。它支持队列的所有操作,您只需使用for(auto& x:qu). 它比使用队列的临时副本进行迭代要高效得多。