Verschiedene Möglichkeiten zum Anhängen von zwei Vektoren in C++ STL

Verschiedene Möglichkeiten zum Anhängen von zwei Vektoren in C++ STL

In diesem Artikel haben wir verschiedene Möglichkeiten zum Anhängen von zwei Vektoren in C++ STL untersucht, darunter std::copy, insert, concat, überladener + Operator und andere Funktionen.

Inhaltsverzeichnis

  1. STL vs. Standardbibliothek
  2. Vektorklasse
  3. Verschiedene Möglichkeiten zum Anhängen mit der Vektorklasse
    • am Anfang des Vektors
    • am Ende des Vektors
    • an einem bestimmten Index
  4. Andere Möglichkeiten
    • std::copy-Funktion
    • benutzerdefinierte concat-Funktion
    • benutzerdefinierte Überladungsoperatoren + und +=

1. STL vs. Standardbibliothek

STL steht für Standard Template Library und ist, wie der Name schon sagt, eine Bibliothek aus generischen Klassen. Die Syntax, um eine davon zu deklarieren, lautet:

template <class local_type_name> class class_name

Das bedeutet, dass wir eine Klasse mit einigen generischen Typmitgliedern deklarieren können, dh einem Mitglied, dessen Typ wir von Anfang an nicht kennen. Verwirren Sie nicht das erste Wort Klasse die hier verwendet wird, um den generischen Typ des local_type_name zu symbolisieren die verwendet werden, mit der Deklaration einer Klasse.
Es kann mehr als eine generische Typdeklaration verwendet werden, wie wir im nächsten Beispiel sehen können:

#include<iostream>
using namespace std;

template <class A, class B> class C
{
    public: A a; B b; // generic type members
    C (A x, B y) {a = x; b = y; } // constructor
    void print() {cout << a << "\n" << b; } // function member
};
int main()
{
    C <int, float> obj_name (3, 3.14);
    obj_name.print();

    return 0;
}

Der Unterschied zwischen den beiden Bibliotheken besteht darin, dass die STL mit generischen Typen arbeitet, während die Standardbibliothek mit Klassen impliziter Typen arbeitet. Ein Beispiel für eine STL-Klasse ist der Vektor Klasse und ein Beispiel für die Standardbibliothek könnte die Zeichenfolge sein Klasse. Beide Klassen verwenden fast dasselbe Verhalten, der einzige Unterschied besteht in den Typen, die sie manipulieren.

2. Vektorklasse

Wir haben bereits gesehen, wie eine generische Klasse definiert wird. Sehen wir uns nun an, was die Definition des Vektors ist

template < class T, class Alloc = allocator<T> > class vector;

Also hat ein Vektor im Grunde ein T generischer Typ, der als Mitgliedstyp vector::value_type aliasiert ist, und ein Alloc Typ mit Alias ​​als Mitgliedstyp vector::allocator_type.

Über T Wir haben früher gesehen, welche Formen angenommen werden können, einen impliziten oder einen definierten Typ.

Was ist mit dem Alloc?

Dies ist der Typ des Zuordnungsobjekts, das zum Definieren des Speicherzuordnungsmodells verwendet wird. Standardmäßig der Allocator Klassenvorlage verwendet, die das einfachste Speicherzuweisungsmodell definiert und wertunabhängig ist.

Um Vektorobjekte zu verwenden, müssen wir die Vektor-Header-Datei einbinden.

#include <vector>

Einige Beispiele für Deklarationen:

vector<int> first;
vector<int> second (4,100);                       // four ints with value 100
vector<int> third (second.begin(),second.end());  // iterating through second
vector<int> fourth (third);                       // a copy of third

Beachten Sie die Verwendung von nur einem Argument im generischen Typ, der Alloc-Typ wird standardmäßig initialisiert.

Der Iterator-Konstruktor kann auch verwendet werden, um aus Arrays zu konstruieren, wie im nächsten Beispiel:

int v[3] = {1,2,3};
vector<int> fifth ( &*v , &*v+3 );

Beachten Sie die Adressierung von v, die beim Zeiger v beginnt und an dessen Ende endet;

Da &und * komplementäre Funktionen sind, könnte die obige Anweisung einfach geschrieben werden:

int v[3] = {1,2,3};
vector<int> fifth ( v , v+3 );

und wenn wir die Dimension von v

nicht kennen würden
int v[] = {1,2,3};
vector<int> fifth ( v , v + sizeof(v) / sizeof(int) );

Um alle Elemente des Vektors fifth zu durchlaufen wir können den Iterator verwenden Klasse wie in der nächsten Anweisung gezeigt:

vector<int>::iterator i;

for ( i = fifth.begin(); i != fifth.end(); i++ )
    cout<< *i <<" ";

Der vollständige Code ist brach

    #include <iostream>
    #include <vector>
    using namespace std;

    int main()
    {
        vector<int> first;
        vector<int> second (4,100);                       
        vector<int> third (second.begin(),second.end());  
        vector<int> fourth (third);                       

        int v[] = {1,2,3};

        vector<int> fifth ( v , v + sizeof(v) / sizeof(int) );

        vector<int>::iterator i;

        for ( i = fifth.begin(); i != fifth.end(); i++ )
            cout<< *i <<" ";

        return 0;
    }

3. Verschiedene Möglichkeiten zum Anhängen

Nachdem wir einige Vektoren definiert haben, können wir als Nächstes Elemente davon manipulieren. Eine Möglichkeit ist das Anhängen von Methoden, die in verschiedenen Fällen vorkommen können:

  • am Anfang des Vektors

wir können die Einfügefunktion verwenden, um am Anfang der Fünfte einzufügen Vektor her Vektor, und dafür müssen wir seine volle Dimension angeben

    vector<int>::iterator i;
    i = fifth.begin();
    fifth.insert( i, fourth.begin(), fourth.end() );
  • am Ende des Vektors

Wir haben hier zwei Methoden, eine besteht darin, nur das vorherige Beispiel zu verwenden, anstatt i zu initialisieren mit Beginn der Fünfte wir werden es mit dem Ende initialisieren

    vector<int>::iterator i;
    i = fifth.end();
    fifth.insert( i, fourth.begin(), fourth.end() );

und die zweite ist die Verwendung von push_back Funktion elementweise

    vector<int>::iterator i;
    for ( i = fourth.begin(); i != fourth.end() ; i++ ) 
        fifth.push_back ( *i );
  • an einem bestimmten Index

Wir können den gleichen Ansatz wie beim Einfügen am Anfang verwenden, nur müssen wir mit der Anzahl der Elemente summieren, nach denen wir anhängen möchten, und eine Bedingung hinzufügen, um zu prüfen, ob i liegt außerhalb des Gültigkeitsbereichs.

    vector<int>::iterator i;
    i = fifth.begin() + 2;
    if ( *i != NULL )
        fifth.insert( i, fourth.begin(), fourth.end() );

4. Andere Wege

  • Kopierfunktion

Definition der Kopierfunktion ist:

    template <class InputIterator, class OutputIterator>
      OutputIterator copy (InputIterator first, InputIterator last, OutputIterator result);

und das nächste Beispiel wird eine Kopie des vierten erstellen Elemente über der Fünfte Vektor:

    copy(fourth.begin() , fourth.end() , back_inserter(fifth) );

Hier haben wir den back_inserter verwendet Funktion, die einen Back-Insert-Iterator konstruiert, der neue Elemente am Ende von x einfügt. Ein Back-Insert-Iterator ist eine spezielle Art von Ausgabe-Iterator, der entwickelt wurde, um Algorithmen, die normalerweise Elemente überschreiben, zu ermöglichen, stattdessen automatisch neue Elemente am Ende des Containers einzufügen.

  • benutzerdefinierte concat-Funktion

    Wir können unsere eigene Funktion definieren, um eine Verkettung von 2 Vektoren zu implementieren, aber es ist zwingend erforderlich, den Vektor einzuschließen und Algorithmus Kopfzeilen
    #include <iostream>
    #include <vector>
    #include <algorithm>
    using namespace std;
    
    template<typename T> void concat( vector<T>& a, vector<T>& b)
        {
         for_each( b.begin(), b.end(), [&](int value){ a.push_back(value); } );
        }

der nächste Aufruf fügt die Elemente der vierten hinzu Vektor am Ende des fünften Vektor

    concat( fifth, fourth);
  • benutzerdefinierte Überladungsoperatoren + und +=

Die attraktivste Art, Code in C++ zu schreiben, ist das Überladen einfacher Operatoren.
In diesem Fall können wir die Operatoren + und +=überdenken, um zwei Vektoren zu verketten.
Der Operator + benötigt einen zusätzlichen Vektor, um die Informationen zu speichern, während der Operator +=Elemente an den ersten anhängt.

Implementierung für + Operator

    template <typename T> vector<T> operator + ( vector<T>& a, vector<T>& b) 
        {
        vector <T> c = a;
        c.insert(c.end(), b.begin(), b.end() );
        return c;  
        }
    fifth = fifth + fourth;

Implementierung für +=Operator

    template <typename T> vector<T>& operator += ( vector<T>& a, vector<T>& b) 
        {
        a.insert(a.end(), b.begin(), b.end() );
        return a;
        }
    fifth += fourth;

Ein nützlicher Hinweis
Eine allgemeine Leistungssteigerung für Verketten besteht darin, die Größe der Vektoren zu überprüfen und denjenigen mit den kleinsten Elementen an den größeren anzuhängen.

    if(fourth.size() > fifth.size()) {
        fourth.insert(fourth.end(), fifth.begin(),fifth.end());
    } else {
        fifth.insert(fifth.end(), fourth.begin(),fourth.end());
    }

No