Namensräume
Varianten
Aktionen

std::random_shuffle, std::shuffle

Von cppreference.com
< cpp‎ | algorithm
 
 
Algorithmenbibliothek
Beschränkte Algorithmen und Algorithmen für Bereiche (C++20)
Beschränkte Algorithmen, z.B. ranges::copy, ranges::sort, ...
Ausführungsrichtlinien (C++17)
Nicht-modifizierende Sequenzoperationen
Stapeloperationen
(C++17)
Suchoperationen
(C++11)                (C++11)(C++11)

Modifizierende Sequenzoperationen
Kopieroperationen
(C++11)
(C++11)
Tauschoperationen
Transformationsoperationen
Generierungsoperationen
Entfernungsoperationen
Ordnungsändernde Operationen
random_shuffleshuffle
(bis C++17)(C++11)
(C++20)(C++20)
Stichprobenoperationen
(C++17)

Sortier- und verwandte Operationen
Partitionierungsoperationen
Sortieroperationen
Binäre Suchoperationen
(auf partitionierten Bereichen)
Mengenoperationen (auf sortierten Bereichen)
Zusammenführungsoperationen (auf sortierten Bereichen)
Heapoperationen
Minimum/Maximum-Operationen
(C++11)
(C++17)
Lexikographische Vergleichsoperationen
Permutationsoperationen
C-Bibliothek
Numerische Operationen
Operationen auf uninitialisiertem Speicher
 
Definiert in Header <algorithm>
template< class RandomIt >
void random_shuffle( RandomIt first, RandomIt last );
(1) (deprecated in C++14)
(removed in C++17)
(2)
template< class RandomIt, class RandomFunc >
void random_shuffle( RandomIt first, RandomIt last, RandomFunc& r );
(bis C++11)
template< class RandomIt, class RandomFunc >
void random_shuffle( RandomIt first, RandomIt last, RandomFunc&& r );
(seit C++11)
(deprecated in C++14)
(removed in C++17)
template< class RandomIt, class URBG >
void shuffle( RandomIt first, RandomIt last, URBG&& g );
(3) (seit C++11)

Ordnet die Elemente im gegebenen Bereich [firstlast) so um, dass jede mögliche Permutation dieser Elemente mit gleicher Wahrscheinlichkeit erscheint.

1) Die Quelle der Zufälligkeit ist implementierungsabhängig, aber die Funktion std::rand wird oft verwendet.
2) Die Quelle der Zufälligkeit ist das Funktions-Objekt r.
Wenn eine der folgenden Bedingungen erfüllt ist, ist das Verhalten undefiniert
  • Der Rückgabetyp von r ist nicht konvertierbar nach std::iterator_traits<RandomIt>::difference_type.
  • Bei einem positiven Wert n vom Typ std::iterator_traits<RandomIt>::difference_type ist das Ergebnis von r(n) kein zufällig gewählter Wert im Intervall [0n).
3) Die Quelle der Zufälligkeit ist das Objekt g.
Bei dem Typ T als std::remove_reference_t<URBG> ist das Verhalten undefiniert, wenn eine der folgenden Bedingungen erfüllt ist.
(bis C++20)

Wenn der Typ von *first nicht Swappable ist(bis C++11)RandomIt ist kein ValueSwappable(seit C++11) ist das Verhalten undefiniert.

Inhalt

[edit] Parameter

first, last - das Iteratorenpaar, das den Bereich der zufällig zu mischenden Elemente definiert
r - Funktions-Objekt, das einen zufällig ausgewählten Wert zurückgibt
g - Generator-Objekt, das einen zufällig ausgewählten Wert zurückgibt
Typanforderungen
-
RandomIt muss die Anforderungen an einen LegacyRandomAccessIterator erfüllen.

[edit] Komplexität

Genau std::distance(first, last) - 1 Swaps.

[edit] Mögliche Implementierung

Siehe auch die Implementierungen in libstdc++ und 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))]);
    }
}

[edit] Hinweise

Beachten Sie, dass die Implementierung nicht vom Standard diktiert wird. Selbst wenn Sie exakt denselben RandomFunc oder URBG (Uniform Random Number Generator) verwenden, können Sie bei unterschiedlichen Standardbibliotheksimplementierungen unterschiedliche Ergebnisse erzielen.

Der Grund für die Entfernung von std::random_shuffle in C++17 ist, dass die reine Iterator-Version normalerweise von std::rand abhängt, was auch für die Deprezierung diskutiert wird. (std::rand sollte durch die Klassen des <random>-Headers ersetzt werden, da std::rand als schädlich angesehen wird.) Zusätzlich hängt die reine Iterator-Version von std::random_shuffle normalerweise von einem globalen Zustand ab. Der std::shuffle-Algorithmus ist der bevorzugte Ersatz, da er einen URBG als dritten Parameter verwendet.

[edit] Beispiel

Mischt zufällig die Sequenz [110] von ganzen Zahlen

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

Mögliche Ausgabe

8 6 10 4 2 3 7 1 9 5

[edit] Fehlerberichte

Die folgenden Verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.

DR angewendet auf Verhalten wie veröffentlicht Korrigiertes Verhalten
LWG 395 C++98 die Quelle der Zufälligkeit von Überladung (1) war nicht spezifiziert, und
std::rand konnte aufgrund der C-Bibliotheksanforderung nicht die Quelle sein
es ist implementierungsabhängig,
und die Verwendung von std::rand ist erlaubt
LWG 552
(N2423)
C++98 r musste nicht die Quelle
der Zufälligkeit von Überladung (2) sein[1]
Gefordert
  1. Überladung (3) hat denselben Fehler, aber dieser Teil der Auflösung ist für C++98 nicht anwendbar.

[edit] Siehe auch

erzeugt die nächstgrößere lexikographische Permutation eines Bereichs von Elementen
(Funktionsvorlage) [editieren]
erzeugt die nächstkleinere lexikographische Permutation eines Bereichs von Elementen
(Funktionsvorlage) [editieren]
Ordnet Elemente in einem Bereich zufällig neu an
(Algorithmus-Funktionsobjekt)[edit]