HOWTO · C++
Vector aleatorio en C++
Este artículo introduce cómo barajar un vector en C++
En esta página
Para reordenar aleatoriamente y en el mismo vector los elementos de un vector de C++, llama a std::shuffle con los iteradores begin() y end() del vector y un motor de números aleatorios. El algoritmo reorganiza los elementos del rango indicado; no crea un segundo vector. Usa una semilla fija para el motor si necesitas una secuencia repetible de elecciones pseudoaleatorias, o siémbralo con una fuente adecuada si quieres que las distintas ejecuciones normalmente produzcan secuencias diferentes.
Mezclar un vector con std::shuffle
std::shuffle se declara en la cabecera <algorithm>. Sus dos primeros argumentos delimitan un rango de iteradores semiabierto: el primer iterador apunta al primer elemento que se incluye y el segundo, justo después del último. Por tanto, para un vector, values.begin() y values.end() abarcan todo el vector. El tercer argumento es un generador de bits aleatorios uniforme (UniformRandomBitGenerator), normalmente un motor como std::mt19937. El motor proporciona los bits aleatorios que se usan para elegir la permutación; no es una función de retorno que entregue un vector ya mezclado.
Este ejemplo completo usa una semilla fija para que el motor parta del mismo estado cada vez que se ejecuta el programa. std::shuffle no garantiza un orden mezclado concreto: este puede variar según la implementación de la biblioteca estándar. Por eso, considera la salida siguiente como un ejemplo, no como una secuencia garantizada.
Ejecuta este ejemplo:
#include <algorithm>
#include <cstddef>
#include <iostream>
#include <random>
#include <vector>
int main() {
std::vector<int> values{12, 32, 43, 53, 23, 65, 84};
std::mt19937 engine(42);
std::shuffle(values.begin(), values.end(), engine);
for (std::size_t i = 0; i < values.size(); ++i) {
if (i != 0) {
std::cout << ' ';
}
std::cout << values[i];
}
std::cout << '\n';
}
El vector de entrada es 12 32 43 53 23 65 84. En la ejecución correcta proporcionada, el programa imprimió este orden mezclado:
23 12 43 53 84 65 32
Con una semilla fija, la secuencia del motor pseudoaleatorio es reproducible con la misma implementación y configuración. Esto no garantiza una salida mezclada idéntica en todas las implementaciones de la biblioteca estándar, porque el algoritmo no especifica una única secuencia universal de elecciones. Para obtener variación entre ejecuciones, siembra el motor una vez y reutilízalo para las mezclas, en lugar de crear uno nuevo para cada elemento o cada llamada. A menudo se usa std::random_device como fuente de semillas, pero su comportamiento depende de la implementación y del entorno; no debe presentarse como una garantía de no determinismo ni de aleatoriedad criptográfica.
También puedes expresar el rango con std::begin(values) y std::end(values), disponibles mediante las utilidades estándar para iteradores. Esta forma resulta útil al escribir una función genérica que acepte distintos tipos de contenedores o arreglos integrados. Para una llamada específica con un vector, sus iteradores miembro son directos y claros. En ambos casos, pasa los dos extremos del mismo contenedor y comprueba que el rango incluya los elementos que quieres permutar. La operación cambia el orden del vector en el mismo lugar, así que el código que lo lea o recorra después verá la disposición mezclada.
Gestionar código heredado que usa std::random_shuffle
std::random_shuffle es un algoritmo antiguo de la biblioteca estándar que puede aparecer en código C++ existente. Su disponibilidad depende del estándar del lenguaje seleccionado por el proyecto y de la implementación de la biblioteca que se utilice. Al mantener ese código, comprueba esa configuración antes de dar por hecho que el nombre está disponible. Las sobrecargas antiguas pueden usar una fuente de aleatoriedad definida por la implementación, mientras que las sobrecargas que aceptan un generador tienen requisitos distintos de los del motor que se pasa a std::shuffle.
Para código nuevo o actualizado, prefiere std::shuffle y pasa un motor de números aleatorios explícito. Así, la fuente de aleatoriedad queda visible, puedes controlar la repetibilidad mediante una semilla y evitas depender de la interfaz antigua. No deduzcas, por encontrar std::random_shuffle en una base de código, que esté disponible en todos los modos del compilador, ni que std::shuffle falte en todos los entornos antiguos; la compatibilidad depende de la configuración de la biblioteca estándar y del estándar del lenguaje del proyecto. Si el proyecto debe conservar código heredado, limita esa decisión de compatibilidad al proyecto y compruébala con la configuración del compilador que se usa para compilarlo.