Pergunta

Eu preciso iterar sobre std::queue. www.cplusplus.com diz:

Por padrão, se nenhuma classe recipiente é especificado para uma classe de fila em particular, é usado o deque modelo de classe contêiner padrão.

Assim eu posso de alguma forma chegar ao deque subjacente da fila e iterar sobre ele?

Foi útil?

Solução

Se você precisar iterar sobre um queue então você precisa de algo mais do que uma fila. O ponto dos adaptadores de contentores padrão é proporcionar uma interface mínima. Se você precisa fazer iteração bem, por que não usar um deque (ou lista) em vez?

Outras dicas

Enquanto eu concordo com outros que uso direto de um recipiente iterable é uma solução preferida, eu quero salientar que o apoio suficiente do C ++ garantias padrão para um do-it-yourself solução caso você queira que por qualquer motivo.

Ou seja, você pode herdar de std::queue e usar sua Container c; membro protegido para acesso begin () e end () do recipiente subjacente (desde que tais métodos existem lá). Aqui está um exemplo que funciona em VS 2010 e testado com 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;
}

Você pode salvar a fila original para uma fila temporária. Então você simplesmente fazer o seu pop normais na fila temporária para passar o original, por exemplo:

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

No final, o tmp_q estará vazia mas a fila original é intocado.

Porque não basta fazer uma cópia da fila que você quer iterar e itens remover um de cada vez, imprimi-los como você vai? Se você quiser fazer mais com os elementos como você iterate, em seguida, uma fila é a estrutura de dados errado.

enquanto o Alexey Kukanov resposta pode ser mais eficiente, você também pode iterar através de uma fila de uma forma muito natural, por popping cada elemento da frente da fila, em seguida, empurrando-o para trás:

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

saída:

0 1 4 9 16 25 36 49 64 81 

Se você precisar iterar uma fila ... fila não é o recipiente que você precisa.
Por que você escolheu uma fila?
Por que você não tomar um recipiente que você pode iterar sobre?


1. Se você pegar uma fila, em seguida, você diz que quer quebrar um recipiente em uma 'fila' interface: - frente - costas - empurrar - pop - ...

Se você também quiser iterate, uma fila tem uma interface incorreta. Uma fila é um adaptador que proporciona um subconjunto restrito do recipiente original

definição 2.O de uma fila é um FIFO e, por definição, um FIFO não é iterable

Eu uso algo como isto. Não muito sofisticado, mas deve funcionar.

    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. 
    }

Ele vai trabalhar porque quando você pop algo de Q1, e empurrá-lo para TEM, torna-se o primeiro elemento do TEM. Então, no final TEM torna-se uma réplica do Q1.

Em resumo:. Não

é um corte, vetor uso como recipiente underlaid, assim queue::front voltará referência válida, convertê-lo a um ponteiro iterado até <= queue::back

std::queue é um adaptador de recipiente, e você pode especificar o recipiente utilizado (o padrão é usar um deque). Se você precisar de funcionalidade para além de que o adaptador, em seguida, basta usar um deque ou outro recipiente diretamente.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top