Namespaces
Variants

std::random_shuffle, std::shuffle

Depuis fr.cppreference.net
(Redirigé depuis cpp/algorithm/shuffle)
 
 
Bibliothèque d'algorithmes
Algorithmes contraints et algorithmes sur les vues (ranges) (C++20)
Algorithmes contraints, p. 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)

Tri et opérations associées
Opérations de partitionnement
(C++11)    

Opérations de tri
Opérations de recherche binaire
(sur des plages partitionnées)
Opérations d'ensemble (sur des plages triées)
Opérations de fusion (sur des 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) (obsolète 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)
(obsolète 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 donnée [first, last) de sorte que chaque permutation possible de ces éléments ait une probabilité égale d'apparition.

1) La source de hasard est définie par l'implémentation, mais la fonction std::rand est souvent utilisée.
2) La source de hasard 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 [0, n).
3) La source de hasard 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 uniformes), vous pouvez obtenir des résultats différents avec différentes implémentations de la bibliothèque standard.

La raison de la suppression de std::random_shuffle en C++17 est que la version avec itérateurs uniquement dépend généralement de std::rand, qui est maintenant également discuté pour obsolescence. (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 avec itérateurs uniquement std::random_shuffle dépend généralement d'un état global. L'algorithme shuffle 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 [1, 10] 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 modifiant le comportement suivants 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 de hasard 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 requis comme source
de hasard de la surcharge (2)[1]
requis
  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 prochaine permutation lexicographique plus grande d'une plage d'éléments
(modèle de fonction & objet fonction d'algorithme)
génère la prochaine permutation lexicographique plus petite d'une plage d'éléments
(modèle de fonction & objet fonction d'algorithme)
réordonne aléatoirement les éléments d'une plage
(objet fonction d'algorithme)