Namespaces
Variants

std::random_shuffle, std::shuffle

Depuis fr.cppreference.net
 
 
Bibliothèque d'algorithmes
Algorithmes contraints et algorithmes sur plages (C++20)
Algorithmes contraints, par ex., ranges::copy, ranges::sort, ...
Opérations de séquence non modificatrices    
Opérations par lots
(C++17)
Opérations de recherche
Opérations de séquence modificatrices
Opérations de copie
(C++11)
(C++11)
Opérations d'échange
Opérations de transformation
Opérations de génération
Opérations de suppression
Opérations de changement d'ordre
(jusqu'à C++17)(C++11)
(C++20)(C++20)
Opérations d'échantillonnage
(C++17)

Opérations de tri et connexes
Opérations de partitionnement
(C++11)    

Opérations de tri
Opérations de recherche binaire
(sur plages partitionnées)
Opérations d'ensemble (sur plages triées)
Opérations de fusion (sur plages triées)
Opérations de tas
Opérations minimum/maximum
(C++11)
(C++17)
Opérations de comparaison lexicographique
Opérations de permutation


 
Défini dans l'en-tête <algorithm>
template< class RandomIt >
void random_shuffle( RandomIt first, RandomIt last );
(1) (déprécié en C++14)
(supprimé en C++17)
template< class RandomIt, class RandomFunc >
void random_shuffle( RandomIt first, RandomIt last, RandomFunc& r );
(2) (jusqu'à C++11)
template< class RandomIt, class RandomFunc >
void random_shuffle( RandomIt first, RandomIt last, RandomFunc&& r );
(depuis C++11)
(déprécié en C++14)
(supprimé en C++17)
template< class RandomIt, class URBG >
void shuffle( RandomIt first, RandomIt last, URBG&& g );
(3) (depuis C++11)

Réordonne les éléments dans la plage [firstlast) donnée de sorte que chaque permutation possible de ces éléments ait une probabilité égale d'apparition.

1) La source d'aléa est définie par l'implémentation, mais la fonction std::rand est souvent utilisée.
2) La source d'aléa est l'objet fonction r.
Si l'une des conditions suivantes est satisfaite, le comportement est indéfini :
  • Le type de retour de r n'est pas convertible en std::iterator_traits<RandomIt>::difference_type.
  • Étant donné une valeur positive n de type std::iterator_traits<RandomIt>::difference_type, le résultat de r(n) n'est pas une valeur choisie aléatoirement dans l'intervalle [0n).
3) La source d'aléa est l'objet g.
Étant donné le type T comme std::remove_reference_t<URBG>, si l'une des conditions suivantes est satisfaite, le comportement est indéfini :
  • T::result_type n'est pas convertible en std::iterator_traits<RandomIt>::difference_type.
(jusqu'à C++20)

Si le type de *first n'est pas Swappable(jusqu'à C++11)RandomIt n'est pas ValueSwappable(depuis C++11), le comportement est indéfini.

Paramètres

first, last - la paire d'itérateurs définissant la plage d'éléments à mélanger aléatoirement
r - objet fonction retournant une valeur choisie aléatoirement
g - objet générateur retournant une valeur choisie aléatoirement
Exigences de type
-
RandomIt doit satisfaire les exigences de LegacyRandomAccessIterator.

Complexité

Exactement std::distance(first, last) - 1 échanges.

Implémentation possible

Voir aussi les implémentations dans libstdc++ et 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) is not actually correct, because the generated number is
        // not uniformly distributed for most values of i. The correct code would be
        // a variation of the C++11 std::uniform_int_distribution implementation.
    }
}
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))]);
    }
}

Notes

Notez que l'implémentation n'est pas dictée par la norme, donc même si vous utilisez exactement le même RandomFunc ou URBG (Générateur de nombres aléatoires uniforme), vous pouvez obtenir des résultats différents avec des implémentations de bibliothèque standard différentes.

La raison de la suppression de std::random_shuffle en C++17 est que la version uniquement itérateur dépend généralement de std::rand, qui est maintenant également discutée pour la dépréciation. (std::rand devrait être remplacé par les classes de l'en-tête <random>, car std::rand est considéré comme nuisible.) De plus, la version uniquement itérateur std::random_shuffle dépend généralement d'un état global. L'algorithme de mélange de std::shuffle est le remplacement préféré, car il utilise un URBG comme 3ème paramètre.

Exemple

Mélange aléatoirement la séquence [110] d'entiers :

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

Sortie possible :

8 6 10 4 2 3 7 1 9 5

Rapports de défauts

Les rapports de défauts suivants modifiant le comportement ont été appliqués rétroactivement aux normes C++ précédemment publiées.

DR Appliqué à Comportement tel que publié Comportement correct
LWG 395 C++98 la source d'aléa de la surcharge (1) n'était pas spécifiée, et
std::rand ne pouvait pas être la source en raison de l'exigence de la bibliothèque C
elle est définie par l'implémentation,
et l'utilisation de std::rand est autorisée
LWG 552
(N2423)
C++98 r n'était pas obligée d'être la source
d'aléa de la surcharge (2)[1]
obligatoire
  1. La surcharge (3) a le même défaut, mais cette partie de la résolution ne s'applique pas à C++98.

Voir aussi

génère la permutation lexicographique suivante plus grande d'une plage d'éléments
(gabarit de fonction & objet fonction d'algorithme)
génère la permutation lexicographique suivante plus petite d'une plage d'éléments
(gabarit de fonction & objet fonction d'algorithme)
réordonne aléatoirement les éléments dans une plage
(objet fonction d'algorithme)