Formas de iterar sobre Vector en C++ STL

Formas de iterar sobre Vector en C++ STL

En este artículo, hemos explorado diferentes formas de iterar sobre Vector en C++ STL. Estos incluyen técnicas como indexación, iteradores, bucle for basado en rango y mucho más.

Los vectores son contenedores de secuencias similares a los arreglos dinámicos. Los vectores tienen la capacidad de cambiar su tamaño. Los datos en los vectores se almacenan de forma conjunta. Por lo tanto, no solo se puede acceder a los datos a través de iteradores y sino también a través de índices .

Cuando escribimos código en C ++, nos encontramos en un dilema constante de qué manera debemos iterar sobre una colección. Obviamente, depende del tipo de estructura de datos que estamos tratando de iterar. Pero, la mayoría de ellos de todos modos siguen la misma estructura. Ahora veremos varias formas de iterar sobre un vector en C++ STL. Luego intentaremos imprimir el contenido de la matriz usando las formas que exploramos.

Las diferentes formas de iterar sobre Vector en C++ STL son:

  • Iterar utilizando la indexación
  • Uso de iteradores
  • Usando bucle for basado en rango
  • Uso de std::for_each

Iterar utilizando la indexación

El uso de la indexación es la forma de libro de texto para iterar sobre un vector usando bucles normales. Nos permite saber la posición exacta del índice de los elementos a los que estamos accediendo. El bucle for se puede utilizar para acceder al vector desde una posición a una última posición.

Pseudocódigo

  1. iniciar y llenar un vector
  2. bucle desde i =0 hasta el tamaño del vector
  3. imprime el elemento del vector en el índice i

Complejidad

  • Algunas personas pueden dudar en usar este código debido a la llamada de vector::size en cada iteración, sin embargo, tiene una complejidad de tiempo constante, por lo que no hay nada de qué preocuparse
  • Complejidad de tiempo en el peor de los casos:Θ(n)
  • Complejidad de tiempo de caso promedio:Θ(n)
  • Complejidad de tiempo en el mejor de los casos:Θ(n)
  • Complejidad del espacio:Θ(1)

Implementación

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

Aplicaciones

  • Este método puede ser útil cuando necesita usar el índice (p. ej., acceder al elemento siguiente/anterior, usar el índice dentro del ciclo)
  • Este método también es excelente cuando necesita un paso que no sea 1. Esto se puede cambiar reemplazando la parte de actualización del ciclo for con algo como i +=2 para acceder solo a elementos alternativos.

Uso de iteradores

Los iteradores se utilizan para iterar sobre una colección de datos. Cuando pensamos en iteradores, generalmente pensamos en la recopilación de datos y las formas de iterar sobre ellos. Usando vector::begin() y vector::end() nos permite acceder a los punteros para iniciar y finalizar el vector respectivamente. También vector::rbegin() y vector::rend() también se puede usar de manera similar.

Pseudocódigo

  1. iniciar y llenar un vector
  2. bucle desde iter =principio del vector al final del vector
  3. dentro del bucle puede acceder a elementos individuales eliminando la referencia a iter

Complejidad

  • vector::begin() y vector::end() tener una complejidad de Θ(1) por lo tanto, no afectan la complejidad del tiempo.
  • Complejidad de tiempo en el peor de los casos:Θ(n)
  • Complejidad de tiempo de caso promedio:Θ(n)
  • Complejidad de tiempo en el mejor de los casos:Θ(n)
  • Complejidad del espacio:Θ(1)

Implementación

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

Aplicaciones

  • Al igual que cuando usamos índices aquí, también podemos controlar la zancada de manera similar a lo que se discutió anteriormente.
  • Usar iteradores nos brinda una ventaja significativa:permite la abstracción. Nos permitirá escribir código genérico que se puede usar con varios contenedores y no necesariamente se limita a solo vectores, lo que hace que nuestro código sea más reutilizable.

Uso de bucle basado en rango

Los bucles for basados ​​en rango se introdujeron en C++ 11 y se ejecutan en un rango. Los bucles for basados ​​en rango ayudan a que nuestro código sea más legible. Proporciona una forma elegante y limpia de acceder a los elementos. Una vez que miras el código, puede parecerte brujería, pero bajo el capó, está usando la lógica que vimos arriba.

Pseudocódigo

para (declaración:rango)
expresión de bucle

  • declaración es una variable del mismo tipo que el tipo de datos del vector al que se le asignan valores
  • rango es la expresión que muestra el rango en el que se ejecutará el bucle for
  • expresión de bucle aquí se refiere al cuerpo del bucle

Complejidad

  • Complejidad de tiempo en el peor de los casos:Θ(n)
  • Complejidad de tiempo de caso promedio:Θ(n)
  • Complejidad de tiempo en el mejor de los casos:Θ(n)
  • Complejidad del espacio:Θ(1)

Implementaciones

#include <vector>
#include <iostream>

using namespace std;

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

Aplicaciones

  • Si no necesita acceder al índice y no necesita iterar sobre el vector en un orden particular. Los bucles for basados ​​en RANge hacen que nuestro código sea más fácil de entender
  • cuando necesitamos iterar todo el vector, esto nos ayuda a escribir menos detallado.

Usando std::for_each

Además de los algoritmos de bucle genéricos, a saber, for loop, while loops y do while loop. for_each nos permite iterar sobre una matriz o colección y ejecutar un bloque de instrucciones sobre cada elemento de la colección.

Pseudocódigo

  1. Inicializar y completar un vector
  2. for_each(comienzo, final, sentencias)

comenzar significa el comienzo del rango
fin significa fin de rango
declaraciones referirse a las funciones a realizar en cada elemento

Complejidad

  • Complejidad de tiempo en el peor de los casos:Θ(nx)
  • Complejidad de tiempo de caso promedio:Θ(nx)
  • Complejidad de tiempo en el mejor de los casos:Θ(nx)
  • Complejidad del espacio:Θ(ny)
  • Aquí x es mejor/promedio/peor caso tiempo complejidad de declaraciones
  • Aquí y es la complejidad espacial de las sentencias

Implementaciones

Para un solo código, use la reducción de la siguiente manera:

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

Aplicaciones

  • Es genérico y, por lo tanto, no se limita a un tipo de contenedor, por lo que cambiar el tipo de contenedor en el que itera es sencillo
  • Nos permite aplicar efectos secundarios en el objeto de función.

Pregunta 1

Qué funcionalidad se agregó en C++ 11 con el objetivo de reducir los detalles innecesarios

std::for_eachrange basado en loopwhile loopiterators

Pregunta 2

Lo que nos permite realizar un bloque de sentencias sobre elementos de vector pasando objetos de función por referencia

rango basado para loopiteratorsstd::for_eachtodos estos

Pregunta 3

¿Cuáles son las desventajas del bucle for basado en rango

no puede controlar la zancada nos permite escribir menos código nos da acceso a indexar todos estos