web-dev-qa-db-fra.com

itération std :: queue

J'ai besoin d'itérer sur std::queue. www.cplusplus.com dit:

Par défaut, si aucune classe de conteneur n'est spécifiée pour une classe de file d'attente particulière, le modèle de classe de conteneur standard est utilisé.

Alors, puis-je en quelque sorte accéder au deque sous-jacent de la file d'attente et le parcourir par la suite?

63
jackhab

Si vous avez besoin d'itérer sur un queue alors vous avez besoin de plus que d'une file d'attente. L’intérêt des adaptateurs de conteneur standard est de fournir une interface minimale. Si vous devez également effectuer une itération, pourquoi ne pas simplement utiliser un deque (ou une liste) à la place?

63
CB Bailey

Bien que je convienne avec d'autres que l'utilisation directe d'un conteneur itérable est une solution à privilégier, je tiens à souligner que la norme C++ garantit une prise en charge suffisante d'une solution à faire soi-même si vous le souhaitez pour une raison quelconque.

À savoir, vous pouvez hériter de std::queue _ et utilise son membre protégé Container c; pour accéder à begin () et à end () du conteneur sous-jacent (à condition que de telles méthodes y soient présentes). Voici un exemple qui fonctionne dans VS 2010 et testé avec 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;
}
33
Alexey Kukanov

vous pouvez enregistrer la file d'attente d'origine dans une file d'attente temporaire. Ensuite, vous faites simplement votre apparition normale dans la file d'attente temporaire pour parcourir celle d'origine, par exemple:

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

A la fin, le tmp_q sera vide mais la file d'attente d'origine sera intacte.

9
StupidMe

Pourquoi ne pas simplement faire une copie de la file d'attente sur laquelle vous souhaitez effectuer une itération et supprimer les éléments un à un en les imprimant au fur et à mesure? Si vous voulez faire plus avec les éléments lors de votre itération, une file d'attente est une structure de données incorrecte.

1
Chuck

alors que réponse d'Alexey Kukanov peut être plus efficace, vous pouvez également parcourir une file d'attente de manière très naturelle, en supprimant chaque élément de l'avant de la file d'attente, puis en le poussant à l'arrière:

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

sortie:

0 1 4 9 16 25 36 49 64 81 
0
Vaelus