Iteradores de acceso aleatorio en C++

Después de pasar por la definición de plantilla de varios algoritmos STL como std::nth_element , std::sort , debe haber encontrado su definición de plantilla que consiste en objetos de tipo Iterador de acceso aleatorio . Entonces, ¿qué son y por qué se utilizan?

Los iteradores de acceso aleatorio son uno de los cinco tipos principales de iteradores presentes en la biblioteca estándar de C++, siendo otros:

Los iteradores de acceso aleatorio son iteradores que se pueden usar para acceder a elementos en una posición de desplazamiento arbitraria en relación con el elemento al que apuntan, ofreciendo la misma funcionalidad que los punteros. Los iteradores de acceso aleatorio son los iteradores más completos en términos de funcionalidad . Todos los tipos de punteros también son iteradores de acceso aleatorio válidos.

Cabe señalar que los contenedores como vector, deque admiten iteradores de acceso aleatorio . Esto significa que si declaramos iteradores normales para ellos, serán iteradores de acceso aleatorio, al igual que en el caso de list, map, multimap, set y multiset, son iteradores bidireccionales. 

Además, tenga en cuenta que los algoritmos de Iterator no dependen del tipo de contenedor . Como los iteradores proporcionan un uso común para todos ellos, la estructura interna de un contenedor no importa.

Entonces, de la jerarquía anterior, se puede decir que los iteradores de acceso aleatorio son los más fuertes de todos los tipos de iteradores.

Características sobresalientes:

1) Usabilidad: los iteradores de acceso aleatorio se pueden usar en algoritmos de múltiples pasos , es decir, un algoritmo que implica procesar el contenedor varias veces en varios pasos.

2) Comparación de igualdad/desigualdad: la igualdad de un iterador de acceso aleatorio se puede comparar con otro iterador. Dado que los iteradores apuntan a alguna ubicación, los dos iteradores serán iguales solo cuando apunten a la misma posición, de lo contrario no.

Entonces, las siguientes dos expresiones son válidas si A y B son iteradores de acceso aleatorio:

A == B  // Checking for equality
A != B  // Checking for inequality

3) Desreferenciación: un iterador de acceso aleatorio se puede desreferenciar tanto como un valor r como un valor l.

CPP

// C++ program to demonstrate Random-Access iterator
#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int> v1 = { 10, 20, 30, 40, 50 };
 
    // Declaring an iterator
    vector<int>::iterator i1;
 
    for (i1 = v1.begin(); i1 != v1.end(); ++i1) {
        // Assigning values to locations pointed by iterator
        *i1 = 7;
    }
 
    for (i1 = v1.begin(); i1 != v1.end(); ++i1) {
        // Accessing values at locations pointed by iterator
        cout << (*i1) << " ";
    }
 
    return 0;
}
Producción

7 7 7 7 7 

Entonces, como podemos ver aquí, podemos acceder y asignar valor al iterador, por lo tanto, el iterador es un iterador de acceso aleatorio. 

4) Incrementable: un iterador de acceso aleatorio se puede incrementar, de modo que se refiera al siguiente elemento de la secuencia, usando el operador ++(), como se vio en el código anterior, donde se incrementó i1 en el ciclo for.

Entonces, las siguientes dos expresiones son válidas si A es un iterador de acceso aleatorio:

A++   // Using post increment operator
++A   // Using pre increment operator

5) Decrementable: Al igual que podemos usar el operador ++() con iteradores de acceso aleatorio para incrementarlos, también podemos disminuirlos.

CPP

// C++ program to demonstrate Random Access iterator
#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int> v1 = { 1, 2, 3, 4, 5 };
 
    // Declaring an iterator
    vector<int>::iterator i1;
 
    // Accessing the elements from end using decrement
    // operator
    for (i1 = v1.end() - 1; i1 != v1.begin() - 1; --i1) {
 
        cout << (*i1) << " ";
    }
    return 0;
}
Producción

5 4 3 2 1 

Dado que comenzamos desde el final del vector y luego nos movemos hacia el principio al disminuir el puntero, lo que muestra que el operador de disminución se puede usar con dichos iteradores. 

6) Operadores relacionales: aunque los iteradores bidireccionales no se pueden usar con operadores relacionales como =, los iteradores de acceso aleatorio que tienen una jerarquía más alta admiten todos estos operadores relacionales.

If A and B are Random-access iterators, then

A == B     // Allowed
A <= B     // Allowed

7) Operadores aritméticos: similares a los operadores relacionales, también se pueden usar con operadores aritméticos como +, –, etc. Esto significa que los iteradores de acceso aleatorio pueden moverse tanto en la dirección como al azar.

If A and B are Random-access iterators, then

A + 1     // Allowed
B - 2     // Allowed

CPP

// C++ program to demonstrate Random Access Iterator
#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int> v1 = { 1, 2, 3, 4, 5 };
 
    // Declaring first iterator
    vector<int>::iterator i1;
 
    // Declaring second iterator
    vector<int>::iterator i2;
 
    // i1 points to the beginning of the list
    i1 = v1.begin();
 
    // i2 points to the end of the list
    i2 = v1.end();
 
    // Applying relational operator to them
    if (i1 < i2) {
        cout << "Yes";
    }
 
    // Applying arithmetic operator to them
    int count = i2 - i1;
 
    cout << "\ncount = " << count;
    return 0;
}
Producción

Yes
count = 5

Aquí, dado que i1 apunta al principio e i2 apunta al final, entonces i2 será mayor que i1 y también una diferencia entre ellos será la distancia total entre ellos. 

8) Uso del operador de desreferencia de desplazamiento ([ ]): los iteradores de acceso aleatorio admiten el operador de desreferencia de desplazamiento ([ ]), que se utiliza para el acceso aleatorio.

If A is a Random-access iterator, then
A[3]    // Allowed 

CPP

// C++ program to demonstrate Random Access iterator
#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int> v1 = { 1, 2, 3, 4, 5 };
    int i;
 
    // Accessing elements using offset dereference
    // operator [ ]
    for (i = 0; i < 5; ++i) {
        cout << v1[i] << " ";
    }
    return 0;
}
Producción

1 2 3 4 5 

9) Intercambiable: el valor al que apuntan estos iteradores se puede intercambiar o canjear.

Implementación práctica: después de comprender sus características, es muy importante conocer también su implementación práctica. Como se dijo anteriormente, los iteradores de acceso aleatorio se pueden usar para todos los propósitos y en todos los escenarios. El siguiente algoritmo STL muestra una de sus implementaciones prácticas: 

std::random_shuffle: Como sabemos, este algoritmo se utiliza para barajar aleatoriamente todos los elementos presentes en un contenedor. Entonces, veamos su funcionamiento interno (no entre en detalles, solo mire dónde se pueden usar los iteradores de acceso aleatorio):

// Definition of std::random_shuffle()
template void random_shuffle(RandomAccessIterator first,
                            RandomAccessIterator last,
                            RandomNumberGenerator& gen)
{
   iterator_traits::difference_type i, n;
   n = (last - first);
   for (i = n - 1; i > 0; --i) {
       swap(first[i], first[gen(i + 1)]);
   }
}

Aquí podemos ver que hemos hecho uso de iteradores de acceso aleatorio, ya que no hay otro tipo de iterador que admita operadores aritméticos, por eso lo hemos usado.

De hecho, si está pensando en usar iteradores de acceso aleatorio, puede usar iterador de acceso aleatorio en lugar de cualquier otro tipo de iterador , ya que es el tipo de iterador más sólido y mejor disponible en la biblioteca estándar de C++.

Este artículo es una contribución de Mrigendra Singh . Si te gusta GeeksforGeeks y te gustaría contribuir, también puedes escribir un artículo usando write.geeksforgeeks.org o enviar tu artículo por correo a review-team@geeksforgeeks.org. Vea su artículo que aparece en la página principal de GeeksforGeeks y ayude a otros Geeks. Escriba comentarios si encuentra algo incorrecto o si desea compartir más información sobre el tema tratado anteriormente.

Publicación traducida automáticamente

Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *