Möglichkeiten zum Iterieren über Vector in C++ STL

Möglichkeiten zum Iterieren über Vector in C++ STL

In diesem Artikel haben wir verschiedene Möglichkeiten zum Iterieren über Vector in C++ STL untersucht. Dazu gehören Techniken wie Indizierung, Iteratoren, bereichsbasierte For-Schleife und vieles mehr.

Vektoren sind Sequenzcontainer, ähnlich wie dynamische Arrays. Vektoren können sich selbst in der Größe ändern. Die Daten in Vektoren werden zusammenhängend gespeichert. Daher kann auf die Daten nicht nur über Iteratoren zugegriffen werden und aber auch durch Indizes .

Wenn wir Code in C++ schreiben, befinden wir uns in einem ständigen Dilemma, auf welche Weise wir eine Sammlung iterieren sollen. Offensichtlich hängt es von der Art der Datenstruktur ab, über die wir iterieren möchten. Aber die meisten von ihnen folgen trotzdem der gleichen Struktur. Jetzt sehen wir verschiedene Möglichkeiten, einen Vektor in C++ STL zu durchlaufen. Dann werden wir versuchen, den Inhalt des Arrays mit den von uns untersuchten Methoden auszudrucken.

Die verschiedenen Möglichkeiten, Vektoren in C++ STL zu durchlaufen, sind:

  • Mit Indizierung iterieren
  • Iteratoren verwenden
  • Bereichsbasierte for-Schleife verwenden
  • Mit std::for_each

Mit Indizierung iterieren

Die Verwendung der Indizierung ist die Lehrbuchmethode zum Iterieren über einen Vektor mit normalen Schleifen. Es ermöglicht uns, die genaue Indexposition der Elemente zu kennen, auf die wir zugreifen. Die for-Schleife kann verwendet werden, um auf den Vektor von einer Position zu einer späteren Position zuzugreifen.

Pseudocode

  1. einen Vektor initialisieren und füllen
  2. Schleife von i =0 bis Größe des Vektors
  3. Element des Vektors bei Index i drucken

Komplexität

  • Einige Leute zögern vielleicht, diesen Code zu verwenden, weil sie bei jeder Iteration von vector::size aufgerufen werden, aber es hat eine konstante Zeitkomplexität, daher ist es kein Grund zur Sorge
  • Worst-Case-Zeitkomplexität:Θ(n)
  • Durchschnittliche Fallzeitkomplexität:Θ(n)
  • Zeitkomplexität im günstigsten Fall:Θ(n)
  • Raumkomplexität:Θ(1)

Implementierung

#include <iostream>
#include <vector>

using namespace std;

int main(){
    vector<int> v = {7, 5, 2, 9, 4, 1};
    for(int i = 0 ; i < v.size(); i++){
        cout << v[i] << " " ;
    }
}

Anwendungen

  • Diese Methode kann hilfreich sein, wenn Sie den Index verwenden müssen (z. B. Zugriff auf das nächste/vorherige Element, Verwendung des Index neben der Schleife)
  • Diese Methode ist auch großartig, wenn Sie einen anderen Schritt als 1 benötigen. Dies kann geändert werden, indem Sie den Aktualisierungsteil der for-Schleife durch etwas wie i +=2 ersetzen, um nur auf alternative Elemente zuzugreifen.

Iteratoren verwenden

Iteratoren werden verwendet, um eine Sammlung von Daten zu durchlaufen. Wenn wir an Iteratoren denken, die wir verwenden, denken wir normalerweise an die Sammlung von Daten und Möglichkeiten, darüber zu iterieren. Mit vector::begin() und vector::end() ermöglichen uns den Zugriff auf Zeiger auf den Start bzw. das Ende des Vektors. Auch vector::rbegin() und vector::rend() kann auch auf ähnliche Weise verwendet werden.

Pseudocode

  1. einen Vektor initialisieren und füllen
  2. Schleife von iter =Vektoranfang bis Vektorende
  3. innerhalb der Schleife können Sie auf einzelne Elemente zugreifen, indem Sie iter dereferenzieren

Komplexität

  • vector::begin() und vector::end() haben eine Komplexität von Θ(1) daher haben sie keinen Einfluss auf die Zeitkomplexität.
  • Worst-Case-Zeitkomplexität:Θ(n)
  • Durchschnittliche Fallzeitkomplexität:Θ(n)
  • Zeitkomplexität im besten Fall:Θ(n)
  • Raumkomplexität:Θ(1)

Implementierung

#include <iostream>
#include <vector>

using namespace std;

int main(){
    vector<int> v = {7, 5, 2, 9, 4, 1};
    // here I used auto to declare it instead of std::vector::iterator
    // to make the code easy to read and understand
    for(auto it = v.begin(); it != v.end(); it++)
        cout << *it << " ";
}

Anwendungen

  • Ähnlich wie hier Indizes verwendet werden, können wir auch den Schritt auf ähnliche Weise wie zuvor besprochen steuern.
  • Die Verwendung von Iteratoren bietet uns einen erheblichen Vorteil:Sie ermöglicht die Abstraktion. Es wird uns ermöglichen, generischen Code zu schreiben, der mit verschiedenen Containern verwendet werden kann und nicht unbedingt nur auf Vektoren beschränkt ist, wodurch unser Code wiederverwendbarer wird.

Bereichsbasierte for-Schleife verwenden

Bereichsbasierte for-Schleifen wurden in C++11 eingeführt und führen eine for-Schleife über einen Bereich aus. Bereichsbasierte for-Schleifen tragen dazu bei, unseren Code lesbarer zu machen. Es bietet eine elegante und saubere Möglichkeit, auf die Elemente zuzugreifen. Wenn Sie sich den Code ansehen, mag er für Sie wie Hexerei aussehen, aber unter der Haube verwendet er die Logik, die wir oben gesehen haben.

Pseudocode

für ( Deklaration :Bereich )
Schleifenausdruck

  • Erklärung ist eine Variable vom gleichen Typ wie der Datentyp des Vektors, dem Werte zugewiesen werden
  • Bereich ist der Ausdruck, der den Bereich angibt, der von der for-Schleife durchlaufen werden soll
  • Schleifenausdruck bezieht sich hier auf den Schleifenkörper

Komplexität

  • Worst-Case-Zeitkomplexität:Θ(n)
  • Durchschnittliche Fallzeitkomplexität:Θ(n)
  • Zeitkomplexität im besten Fall:Θ(n)
  • Raumkomplexität:Θ(1)

Implementierungen

#include <vector>
#include <iostream>

using namespace std;

int main(){
    vector<int> v = {7, 5, 2, 9, 4, 1};
    for(int i : v){
        cout << i << " " ;
    }
}

Anwendungen

  • Wenn Sie nicht auf den Index zugreifen und den Vektor nicht in einer bestimmten Reihenfolge durchlaufen müssen. Bereichsbasierte for-Schleifen machen unseren Code leichter verständlich
  • Wenn wir den gesamten Vektor iterieren müssen, helfen uns diese, weniger ausführlich zu schreiben.

Mit std::for_each

Abgesehen von den generischen Schleifenalgorithmen nämlich for loop, while loops und do while loop. for_each ermöglicht es uns, über ein Array oder eine Sammlung zu iterieren und einen Block von Anweisungen über jedes Element der Sammlung auszuführen.

Pseudocode

  1. Initialisieren und füllen Sie einen Vektor
  2. for_each(Beginn, Ende, Anweisungen)

beginnen bezeichnet den Beginn des Bereichs
Ende bedeutet das Ende des Bereichs
Aussagen beziehen sich auf Funktionen, die für jedes Element ausgeführt werden sollen

Komplexität

  • Worst-Case-Zeitkomplexität:Θ(nx)
  • Durchschnittliche Fallzeitkomplexität:Θ(nx)
  • Zeitkomplexität im besten Fall:Θ(nx)
  • Leerzeichenkomplexität:Θ(ny)
  • Hier x ist die beste/durchschnittliche/schlechteste Zeitkomplexität von Aussagen
  • Hier y ist die Raumkomplexität der Anweisungen

Implementierungen

Verwenden Sie für einzelnen Code Markdown wie folgt:

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main(){
    vector<int> v = {7, 5, 2, 9, 4, 1};
    for_each(v.begin(), v.end(), [](int const& val){
        cout << val << " " ;
    });

    return 0;
}

Anwendungen

  • Es ist generisch und daher nicht auf einen Containertyp beschränkt, daher ist das Austauschen des Containertyps, über den es iteriert, problemlos
  • Erlaubt uns, Seiteneffekte auf Funktionsobjekte anzuwenden.

Frage 1

Welche Funktionalität wurde in C++ 11 hinzugefügt, um unnötige Ausführlichkeit zu reduzieren

std::for_eachrange basiert auf Loopwhile-Loopiteratoren

Frage 2

Was uns erlaubt, einen Block von Anweisungen zu Vektorelementen auszuführen, indem Funktionsobjekte per Referenz übergeben werden

range based for loopiteratorsstd::for_eachalle davon

Frage 3

Was sind die Nachteile einer bereichsbasierten For-Schleife

can not control stride ermöglicht es uns, weniger Code zu schreiben gibt uns Zugriff auf alle diese Indexe