Diferentes formas de agregar dos vectores en C++ STL

Diferentes formas de agregar dos vectores en C++ STL

En este artículo, hemos explorado diferentes formas de agregar dos vectores en C++ STL que incluyen std::copy, insert, concat, el operador + sobrecargado y otras funciones.

Tabla de contenido

  1. STL frente a biblioteca estándar
  2. clase vectorial
  3. Diferentes formas de anexar usando la clase vectorial
    • al principio del vector
    • al final del vector
    • en un índice especificado
  4. Otras formas
    • std::función de copia
    • función concat definida por el usuario
    • operadores de sobrecarga definidos por el usuario + y +=

1. STL frente a biblioteca estándar

STL proviene de Standard Template Library y, como su nombre indica, es una biblioteca hecha de clases genéricas. La sintaxis para declarar uno de ellos es:

template <class local_type_name> class class_name

lo que significa que podemos declarar una clase con algunos miembros de tipo genérico, es decir, un miembro del que no conocemos su tipo desde el principio. No se confunda con la primera palabra clase que se utiliza aquí para simbolizar el tipo genérico de local_type_name que se utilizará, con la declaración de una clase.
Se puede utilizar más de una declaración de tipo genérico como podemos ver en el siguiente ejemplo:

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

La diferencia entre las dos bibliotecas es que STL funciona con tipos genéricos mientras que la Biblioteca estándar funciona con clases de tipos implícitos. Un ejemplo de clase STL es el vector clase y un ejemplo de biblioteca estándar podría ser la cadena clase. Ambas clases usan casi el mismo comportamiento, la única diferencia consiste en los tipos que manipulan.

2. clase de vectores

Vimos anteriormente cómo se define una clase genérica. Ahora veamos cuál es la definición del vector

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

Básicamente, un vector tiene una T tipo genérico con alias como tipo de miembro vector::value_type y un Alloc escriba con alias como vector de tipo de miembro::allocator_type.

Acerca de T vimos antes qué formas pueden tomar, un tipo implícito o definido.

¿Qué pasa con Alloc?

Este es el tipo de objeto asignador que se utiliza para definir el modelo de asignación de almacenamiento. De forma predeterminada, el asignador se utiliza la plantilla de clase, que define el modelo de asignación de memoria más simple y es independiente del valor.

Para usar objetos vectoriales debemos incluir el archivo de cabecera del vector.

#include <vector>

Algunos ejemplos de declaraciones:

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

Observe el uso de un solo argumento en el tipo genérico, el tipo Alloc se inicializa de forma predeterminada.

El constructor iterador también se puede usar para construir a partir de matrices como en el siguiente ejemplo:

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

Observe el direccionamiento de v, que comienza desde el puntero v y termina al final de este;

Dado que &y * son funciones complementarias, la declaración anterior podría escribirse simplemente:

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

y si no sabríamos la dimensión de v

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

Para iterar todos los elementos del vector quinto podemos usar el iterador clase como se muestra en la siguiente declaración:

vector<int>::iterator i;

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

El código completo está en barbecho

    #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. Diferentes formas de añadir

Una vez que definimos algunos vectores, lo siguiente que podemos hacer es manipular elementos de ellos. Una forma es agregar un método que podría ser en diferentes casos:

  • al comienzo del vector

podemos usar la función de inserción para insertar al principio de la quinta vector el adelante vector, y para eso necesitamos especificar su dimensión completa

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

tenemos dos métodos aquí, uno es usando el ejemplo anterior solamente, en lugar de inicializar i con el comienzo de la quinta lo inicializaremos con el final

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

y el segundo es usando el push_back función elemento por elemento

    vector<int>::iterator i;
    for ( i = fourth.begin(); i != fourth.end() ; i++ ) 
        fifth.push_back ( *i );
  • en un índice especificado

podemos usar el mismo enfoque que la inserción inicial, solo que necesitamos sumar el número de elementos después de lo cual querremos agregar y agregar una condición para verificar si i está fuera del alcance.

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

4. Otras formas

  • función de copia

La definición de la función de copia es:

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

y el siguiente ejemplo hará una copia del cuarto elementos sobre el quinto vector:

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

Aquí hemos utilizado el back_inserter función que crea un iterador de inserción posterior que inserta nuevos elementos al final de x. Un iterador de inserción posterior es un tipo especial de iterador de salida diseñado para permitir que los algoritmos que generalmente sobrescriben elementos inserten nuevos elementos automáticamente al final del contenedor.

  • función concat definida por el usuario

    Podemos definir nuestra propia función para implementar una concatenación de 2 vectores pero es obligatorio incluir el vector y algoritmo encabezados
    #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); } );
        }

la próxima convocatoria agregará los elementos del cuarto vector al final de la quinta vector

    concat( fifth, fourth);
  • operadores de sobrecarga definidos por el usuario + y +=

La forma más atractiva de escribir código en C++ es sobrecargar los operadores básicos.
En este caso podemos repensar los operadores + y +=para concatenar dos vectores.
El operador + necesita un vector adicional para almacenar la información, mientras que el operador +=agregará elementos al primero.

implementación para el operador +

    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;

implementación para el operador +=

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

Una sugerencia útil
Un aumento de rendimiento general para concatenar es verificar el tamaño de los vectores y agregar el que tiene los elementos más pequeños al más grande.

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

No