Ich muss noch einmal iterieren std::queue
. www.cplusplus.com sagt:
Wenn für eine bestimmte Warteschlangenklasse keine Containerklasse angegeben ist, wird standardmäßig die Standard-Deque der Containerklassenvorlage verwendet.
Kann ich also irgendwie zur zugrunde liegenden Deque der Warteschlange gelangen und darüber iterieren?
c++
queue
iteration
c++-standard-library
Jackhab
quelle
quelle
deque
die Aufzählung nur völlig willkürlich unterstützt wird. Sie könnten genauso gut argumentieren, dassdeque
dies genauso puristisch sein solltequeue
und die Iteration nicht unterstützen sollte, und wenn Sie es iterieren möchten, möchten Sie etwas "mehr"; zB adeque_enumerable
. Es ist jedoch ein rutschiger Hang, und mein persönliches Gefühl ist, dassqueue
dies die Aufzählung an erster Stelle hätte unterstützen sollen.queue
Schnittstelle, also sollten Sie ein Objekt mit einer geeigneten Schnittstelle auswählen." Ob esqueue
Ihnen gefällt oder nicht, die Iteration ist nicht Teil der Benutzeroberfläche. Wenn Sie also eine Iteration wünschen, müssen Sie etwas anderes auswählen.queue
zu sein, Vorwärtsiteratoren zu unterstützen, aber keine Rückwärtsiteratoren, ohne eine vernünftige Implementierung zu belasten, die mir einfällt . Ich denke, CS101-Profis haben sich vielleicht darüber beschwert ...Obwohl ich anderen zustimme, dass die direkte Verwendung eines iterierbaren Containers eine bevorzugte Lösung ist, möchte ich darauf hinweisen, dass der C ++ - Standard eine ausreichende Unterstützung für eine Do-it-yourself-Lösung garantiert, falls Sie dies aus irgendeinem Grund wünschen.
Sie können nämlich von
std::queue
seinem geschützten Mitglied erben und verwenden,Container c;
um auf begin () und end () des zugrunde liegenden Containers zuzugreifen (vorausgesetzt, solche Methoden sind dort vorhanden). Hier ist ein Beispiel, das in VS 2010 funktioniert und mit ideone getestet wurde :#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; }
quelle
deque
direkt verwenden?!Sie können die ursprüngliche Warteschlange in einer temporären Warteschlange speichern. Dann machen Sie einfach Ihren normalen Pop in der temporären Warteschlange, um die ursprüngliche zu durchlaufen, zum Beispiel:
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(); }
Am Ende ist tmp_q leer, aber die ursprüngliche Warteschlange bleibt unberührt.
quelle
std::queue
scheint keine.top()
Methode zu habenstd::queue
die richtige Methode ist.front()
Eine indirekte Lösung kann darin bestehen, stattdessen std :: deque zu verwenden. Es unterstützt alle Operationen der Warteschlange und Sie können sie einfach mit iterieren
for(auto& x:qu)
. Es ist viel effizienter als die Verwendung einer temporären Kopie der Warteschlange für die Iteration.quelle
Warum nicht einfach eine Kopie der Warteschlange erstellen, über die Sie iterieren möchten, und Elemente einzeln entfernen und sie dabei ausdrucken? Wenn Sie beim Iterieren mehr mit den Elementen tun möchten, ist eine Warteschlange die falsche Datenstruktur.
quelle
malloc
/new
), stellen Sie sicher, dassfree
/delete
it vorhanden ist , da sonst Speicherplatz verloren geht.Während die Antwort von Alexey Kukanov effizienter sein kann, können Sie eine Warteschlange auch auf ganz natürliche Weise durchlaufen, indem Sie jedes Element von der Vorderseite der Warteschlange entfernen und dann nach hinten verschieben:
#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(); } }
Ausgabe:
0 1 4 9 16 25 36 49 64 81
quelle
Kurzum: Nein.
Es gibt einen Hack, verwenden Sie den Vektor als unterlegten Container, geben Sie also
queue::front
eine gültige Referenz zurück und konvertieren Sie ihn in einen Zeiger und eine Iteration bis <=queue::back
quelle
Ich benutze so etwas. Nicht sehr raffiniert, sollte aber funktionieren.
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. }
Es wird funktionieren, denn wenn Sie etwas aus q1 entfernen und in tem verschieben, wird es das erste Element von tem. Am Ende wird tem also eine Nachbildung von q1.
quelle
Wenn Sie eine Warteschlange iterieren müssen ... ist die Warteschlange nicht der Container, den Sie benötigen.
Warum hast du eine Warteschlange ausgewählt?
Warum nimmst du nicht einen Container, über den du iterieren kannst?
1.Wenn Sie eine Warteschlange auswählen, möchten Sie einen Container in eine Warteschlangenschnittstelle einbinden: - Front - Back - Push - Pop - ...
Wenn Sie auch iterieren möchten, hat eine Warteschlange eine falsche Schnittstelle. Eine Warteschlange ist ein Adapter, der eine eingeschränkte Teilmenge des ursprünglichen Containers bereitstellt
2. Die Definition einer Warteschlange ist ein FIFO und per Definition ist ein FIFO nicht iterierbar
quelle
std::queue
ist ein Containeradapter, und Sie können den verwendeten Container angeben (standardmäßig wird a verwendetdeque
). Wenn Sie darüber hinaus Funktionen im Adapter benötigen, verwenden Sie einfach einendeque
oder einen anderen Container direkt.quelle