Przejdź do głównej zawartości

std::random_shuffle() algorithm

// (1)
template< class RandomIt >
void random_shuffle( RandomIt first, RandomIt last );

// (2)
template< class RandomIt, class RandomFunc >
void random_shuffle( RandomIt first, RandomIt last, RandomFunc&& r );

Reorders the elements in the given range [first; last) such that each possible permutation of those elements has equal probability of appearance.

  • (1) The source of randomness is implementation-defined

    , but the function std::rand is often used.

  • (2) The source of randomness is the function object r.

Parameters

first
last

The range of elements to shuffle.

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).

Type requirements

RandomItLegacyRandomAccessIterator
ValueSwappable

Return value

(none)

Complexity

Linear in std::distance(first, last).

Exceptions

(none)

Possible implementation

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)]);
}
}

Notes

Note that the implementation is not dictated by the standard, so even if you use exactly the same RandomFunc 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 shuffle algorithm is the preferred replacement, as it uses a URBG as its 3rd parameter.

Main.cpp
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>

int main()
{
std::vector<int> v {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

std::random_shuffle(v.begin(), v.end());

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
This article originates from this CppReference page. It was likely altered for improvements or editors' preference. Click "Edit this page" to see all changes made to this document.
Hover to see the original license.

std::random_shuffle() algorithm

// (1)
template< class RandomIt >
void random_shuffle( RandomIt first, RandomIt last );

// (2)
template< class RandomIt, class RandomFunc >
void random_shuffle( RandomIt first, RandomIt last, RandomFunc&& r );

Reorders the elements in the given range [first; last) such that each possible permutation of those elements has equal probability of appearance.

  • (1) The source of randomness is implementation-defined

    , but the function std::rand is often used.

  • (2) The source of randomness is the function object r.

Parameters

first
last

The range of elements to shuffle.

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).

Type requirements

RandomItLegacyRandomAccessIterator
ValueSwappable

Return value

(none)

Complexity

Linear in std::distance(first, last).

Exceptions

(none)

Possible implementation

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)]);
}
}

Notes

Note that the implementation is not dictated by the standard, so even if you use exactly the same RandomFunc 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 shuffle algorithm is the preferred replacement, as it uses a URBG as its 3rd parameter.

Main.cpp
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>

int main()
{
std::vector<int> v {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

std::random_shuffle(v.begin(), v.end());

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
This article originates from this CppReference page. It was likely altered for improvements or editors' preference. Click "Edit this page" to see all changes made to this document.
Hover to see the original license.