Namespaces
Variants

std:: random_shuffle, std:: shuffle

From cppreference.net
Algorithm library
Constrained algorithms and algorithms on ranges (C++20)
Constrained algorithms, e.g. ranges::copy , ranges::sort , ...
Execution policies (C++17)
Non-modifying sequence operations
Batch operations
(C++17)
Search operations
Modifying sequence operations
Copy operations
(C++11)
(C++11)
Swap operations
Transformation operations
Generation operations
Removing operations
Order-changing operations
random_shuffle shuffle
(until C++17) (C++11)
(C++20) (C++20)
Sampling operations
(C++17)

Sorting and related operations
Partitioning operations
Sorting operations
Binary search operations
(on partitioned ranges)
Set operations (on sorted ranges)
Merge operations (on sorted ranges)
Heap operations
Minimum/maximum operations
Lexicographical comparison operations
Permutation operations
C library
Numeric operations
Operations on uninitialized memory
Definido en el encabezado <algorithm>
template < class RandomIt >
void random_shuffle ( RandomIt first, RandomIt last ) ;
(1) (obsoleto en C++14)
(eliminado en C++17)
(2)
template < class RandomIt, class RandomFunc >
void random_shuffle ( RandomIt first, RandomIt last, RandomFunc & r ) ;
(hasta C++11)
template < class RandomIt, class RandomFunc >
void random_shuffle ( RandomIt first, RandomIt last, RandomFunc && r ) ;
(desde C++11)
(obsoleto en C++14)
(eliminado en C++17)
template < class RandomIt, class URBG >
void shuffle ( RandomIt first, RandomIt last, URBG && g ) ;
(3) (desde C++11)

Reordena los elementos en el rango dado [ first , last ) de tal forma que cada posible permutación de esos elementos tenga igual probabilidad de aparición.

1) La fuente de aleatoriedad está definida por la implementación, pero la función std::rand se utiliza frecuentemente.
2) La fuente de aleatoriedad es el objeto función r .
Si se satisface alguna de las siguientes condiciones, el comportamiento es indefinido:
  • El tipo de retorno de r no es convertible a std:: iterator_traits < RandomIt > :: difference_type .
  • Dado un valor positivo n de tipo std:: iterator_traits < RandomIt > :: difference_type , el resultado de r ( n ) no es un valor elegido aleatoriamente en el intervalo [ 0 , n ) .
3) La fuente de aleatoriedad es el objeto g .
Dado el tipo T como std:: remove_reference_t < URBG > , si alguna de las siguientes condiciones se satisface, el comportamiento es indefinido:
(hasta C++20)

Si el tipo de * first no es Swappable (hasta C++11) RandomIt no es ValueSwappable (desde C++11) , el comportamiento es indefinido.

Contenidos

Parámetros

first, last - el par de iteradores que definen el rango de elementos a barajar aleatoriamente
r - objeto función que devuelve un valor elegido aleatoriamente
g - objeto generador que devuelve un valor elegido aleatoriamente
Requisitos de tipo
-
RandomIt debe cumplir con los requisitos de LegacyRandomAccessIterator .

Complejidad

Exactamente std:: distance ( first, last ) - 1 intercambios.

Implementación posible

Consulte también las implementaciones en libstdc++ y libc++ .

random_shuffle (1)
template<class RandomIt>
void random_shuffle(RandomIt first, RandomIt last)
{
    typedef typename std::iterator_traits<RandomIt>::difference_type diff_t;
    for (diff_t i = last - first - 1; i > 0; --i)
    {
        using std::swap;
        swap(first[i], first[std::rand() % (i + 1)]);
        // rand() % (i + 1) no es realmente correcto, porque el número generado no está
        // distribuido uniformemente para la mayoría de los valores de i. El código correcto sería
        // una variación de la implementación de std::uniform_int_distribution de C++11.
    }
}
random_shuffle (2)
template<class RandomIt, class RandomFunc>
void random_shuffle(RandomIt first, RandomIt last, RandomFunc&& r)
{
    typedef typename std::iterator_traits<RandomIt>::difference_type diff_t;
    for (diff_t i = last - first - 1; i > 0; --i)
    {
        using std::swap;
        swap(first[i], first[r(i + 1)]);
    }
}
shuffle (3)
template<class RandomIt, class URBG>
void shuffle(RandomIt first, RandomIt last, URBG&& g)
{
    typedef typename std::iterator_traits<RandomIt>::difference_type diff_t;
    typedef std::uniform_int_distribution<diff_t> distr_t;
    typedef typename distr_t::param_type param_t;
    distr_t D;
    for (diff_t i = last - first - 1; i > 0; --i)
    {
        using std::swap;
        swap(first[i], first[D(g, param_t(0, i))]);
    }
}

Notas

Tenga en cuenta que la implementación no está dictada por el estándar, por lo que incluso si utiliza exactamente la misma RandomFunc o URBG (Uniform Random Number Generator) puede obtener resultados diferentes con distintas implementaciones de la biblioteca estándar.

La razón para eliminar std::random_shuffle en C++17 es que la versión que solo utiliza iteradores normalmente depende de std::rand , que ahora también se está considerando para su desaprobación. ( std::rand debería ser reemplazado con las clases de la cabecera <random> , ya que std::rand está considerado perjudicial .) Además, la versión de std::random_shuffle que solo utiliza iteradores normalmente depende de un estado global. El algoritmo de mezcla de std::shuffle es el reemplazo preferido, ya que utiliza un URBG como su tercer parámetro.

Ejemplo

Mezcla aleatoriamente la secuencia [ 1 , 10 ] de enteros:

#include <algorithm>
#include <iostream>
#include <iterator>
#include <random>
#include <vector>
int main()
{
    std::vector<int> v{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    std::random_device rd;
    std::mt19937 g(rd());
    std::shuffle(v.begin(), v.end(), g);
    std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " "));
    std::cout << '\n';
}

Salida posible:

8 6 10 4 2 3 7 1 9 5

Informes de defectos

Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares de C++ publicados anteriormente.

DR Aplicado a Comportamiento publicado Comportamiento correcto
LWG 395 C++98 no se especificaba la fuente de aleatoriedad de la sobrecarga (1) , y
std::rand no podía ser la fuente debido al requisito de la biblioteca C
está definido por la implementación,
y se permite usar std::rand
LWG 552
( N2423 )
C++98 r no se requería que fuera la fuente
de aleatoriedad de la sobrecarga (2) [1]
requerido
  1. La sobrecarga (3) tiene el mismo defecto, pero esa parte de la resolución no es aplicable a C++98.

Véase también

genera la siguiente permutación lexicográfica mayor de un rango de elementos
(plantilla de función)
genera la siguiente permutación lexicográfica menor de un rango de elementos
(plantilla de función)
reordena aleatoriamente elementos en un rango
(objeto función de algoritmo)