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
Definiert im Header <algorithm>
template < class RandomIt >
void random_shuffle ( RandomIt first, RandomIt last ) ;
(1) (veraltet in C++14)
(entfernt 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)
(veraltet in C++14)
(entfernt in C++17)
template < class RandomIt, class URBG >
void shuffle ( RandomIt first, RandomIt last, URBG && g ) ;
(3) (seit C++11)

Ordnet die Elemente im angegebenen Bereich [ first , last ) so um, dass jede mögliche Permutation dieser Elemente die gleiche Wahrscheinlichkeit des Auftretens hat.

1) Die Quelle der Zufälligkeit ist implementierungsdefiniert, aber die Funktion std::rand wird häufig verwendet.
2) Die Quelle der Zufälligkeit ist das Funktionsobjekt r .
Wenn eine der folgenden Bedingungen erfüllt ist, ist das Verhalten undefiniert:
  • Der Rückgabetyp von r ist nicht konvertierbar zu std:: iterator_traits < RandomIt > :: difference_type .
  • Für einen 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 [ 0 , n ) .
3) Die Quelle der Zufälligkeit ist das Objekt g .
Gegeben sei der Typ T als std:: remove_reference_t < URBG > , falls eine der folgenden Bedingungen erfüllt ist, ist das Verhalten undefiniert:
(bis C++20)

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

Inhaltsverzeichnis

Parameter

first, last - das Paar von Iteratoren, das den Bereich der zufällig zu mischenden Elemente definiert
r - Funktionsobjekt, das einen zufällig gewählten Wert zurückgibt
g - Generatorobjekt, das einen zufällig gewählten Wert zurückgibt
Typanforderungen
-
RandomIt muss die Anforderungen von LegacyRandomAccessIterator erfüllen.

Komplexität

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

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) ist nicht korrekt, da die generierte Zahl
        // für die meisten Werte von i nicht gleichmäßig verteilt ist. Der korrekte Code wäre
        // eine Variation der C++11 std::uniform_int_distribution Implementierung.
    }
}
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))]);
    }
}

Hinweise

Beachten Sie, dass die Implementierung nicht durch den Standard vorgegeben ist, daher können Sie selbst bei Verwendung exakt derselben RandomFunc oder URBG (Uniform Random Number Generator) mit verschiedenen Standardbibliothek-Implementierungen unterschiedliche Ergebnisse erhalten.

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

Beispiel

Mischt zufällig die Sequenz [ 1 , 10 ] 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

Fehlerberichte

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

DR Angewendet auf Verhalten wie veröffentlicht Korrektes Verhalten
LWG 395 C++98 die Zufallsquelle der Überladung (1) war nicht spezifiziert, und
std::rand konnte aufgrund der C-Bibliotheksanforderung nicht die Quelle sein
es ist implementierungsdefiniert,
und die Verwendung von std::rand ist erlaubt
LWG 552
( N2423 )
C++98 r war nicht als Quelle der Zufälligkeit
für Überladung (2) erforderlich [1]
erforderlich
  1. Überladung (3) hat den gleichen Defekt, aber dieser Teil der Lösung ist nicht auf C++98 anwendbar.

Siehe auch

erzeugt die nächstgrößere lexikografische Permutation eines Elementbereichs
(Funktions-Template)
erzeugt die nächstkleinere lexikografische Permutation eines Elementbereichs
(Funktions-Template)
ordnet Elemente in einem Bereich zufällig neu an
(Algorithmus-Funktionsobjekt)