90

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

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

那么我可以以某种方式到达队列的底层双端队列并对其进行迭代吗?

4

10 回答 10

79

如果您需要迭代 aqueue那么您需要的不仅仅是队列。标准容器适配器的重点是提供最小接口。如果您还需要进行迭代,为什么不直接使用双端队列(或列表)呢?

于 2009-08-11T08:49:44.383 回答
39

虽然我同意其他人的观点,即直接使用可迭代容器是首选解决方案,但我想指出,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;
}
于 2011-05-12T20:39:57.870 回答
19

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

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();
} 

最后, tmp_q 将为空,但原始队列保持不变。

于 2017-04-12T21:19:03.467 回答
5

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

于 2019-12-10T18:29:45.393 回答
2

为什么不直接复制您想要迭代的队列,一次删除一个项目,并在执行过程中打印它们?如果您想在迭代时对元素做更多的事情,那么队列是错误的数据结构。

于 2012-12-04T21:58:23.460 回答
2

虽然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();
    }
}

输出:

0 1 4 9 16 25 36 49 64 81 
于 2019-07-25T14:58:17.063 回答
-1

简而言之:没有。

有一个技巧,使用向量作为底层容器,因此queue::front将返回有效引用,将其转换为指针迭代直到 <=queue::back

于 2009-08-11T08:51:37.953 回答
-1

我用这样的东西。不是很复杂,但应该可以工作。

    queue<int> tem; 

    while(!q1.empty()) // q1 is your initial queue. 
    {
        int u = q1.front(); 

        // do what you need to do with this value.  

        q1.pop(); 
        tem.push(u); 
    }


    while(!tem.empty())
    {
        int u = tem.front(); 
        tem.pop(); 
        q1.push(u); // putting it back in our original queue. 
    }

它会起作用,因为当您从 q1 弹出一些东西并将其推入 tem 时,它会成为 tem 的第一个元素。因此,最终 tem 成为 q1 的复制品。

于 2018-11-27T11:17:18.513 回答
-2

如果您需要迭代队列......队列不是您需要的容器。
你为什么选择排队?
为什么不使用可以迭代的容器?


1.如果你选择一个队列,那么你说你想将一个容器包装到一个“队列”界面中: - 前 - 后 - 推 - 弹出 - ...

如果您还想迭代,队列的接口不正确。队列是提供原始容器的受限子集的适配器

2.队列的定义是先进先出,按照定义先进先出是不可迭代的

于 2009-08-11T08:52:43.207 回答
-2

std::queue是一个容器适配器,你可以指定使用的容器(默认使用 a deque)。如果您需要适配器之外的功能,则只需deque直接使用一个或另一个容器。

于 2012-12-04T15:55:52.037 回答