Defined 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 ); | (until C++11) | |
template< class RandomIt, class RandomFunc > void random_shuffle( RandomIt first, RandomIt last, RandomFunc&& r ); | (since C++11) (deprecated in C++14) (removed in C++17) | |
template< class RandomIt, class URBG > void shuffle( RandomIt first, RandomIt last, URBG&& g ); | (3) | (since C++11) |
Reorders the elements in the given range [
first
,
last
)
such that each possible permutation of those elements has equal probability of appearance.
std::rand
is often used.r
.g
.first, last | - | the range of elements to shuffle randomly |
r | - | function object returning a randomly chosen value of type convertible to std::iterator_traits<RandomIt>::difference_type in the interval [ 0 , n ) if invoked as r(n) |
g | - | a UniformRandomBitGenerator whose result type is convertible to std::iterator_traits<RandomIt>::difference_type |
Type requirements | ||
-RandomIt must meet the requirements of ValueSwappable and LegacyRandomAccessIterator. |
||
-std::remove_reference_t<URBG> must meet the requirements of UniformRandomBitGenerator. |
(none).
Linear in the distance between first
and last
.
Note that the implementation is not dictated by the standard, so even if you use exactly the same RandomFunc
or URBG
(Uniform Random Number Generator) you may get different results with different standard library implementations.
The reason for removing std::random_shuffle
in C++17 is that the iterator-only version usually depends on std::rand
, which is now also discussed for deprecation. (std::rand
should be replaced with the classes of the <random>
header, as std::rand
is considered harmful.) In addition, the iterator-only std::random_shuffle
version usually depends on a global state. The std::shuffle
's shuffle algorithm is the preferred replacement, as it uses a URBG
as its 3rd parameter.
See also the implementations in libstdc++ and 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. A correct implementation // will need to essentially reimplement C++11 std::uniform_int_distribution, // which is beyond the scope of this example. } } |
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 |
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))]); } } |
The following code randomly shuffles the integers 1~10:
#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'; }
Possible output:
8 6 10 4 2 3 7 1 9 5
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
LWG 395 | C++98 | the source of randomness of overload (1) was not specified, andstd::rand could not be the source due to the C library requirement | it is implementation-defined, and using std::rand is allowed |
LWG 552 (N2423) | C++98 | r was not required to be the sourceof randomness of overload (2)[1] | required |
generates the next greater lexicographic permutation of a range of elements (function template) |
|
generates the next smaller lexicographic permutation of a range of elements (function template) |
|
(C++20) | randomly re-orders elements in a range (niebloid) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/algorithm/random_shuffle