Namespaces
Variants
Views
Actions

std::random_shuffle, std::shuffle

From cppreference.com
< cpp | algorithm
Revision as of 05:19, 3 July 2012 by P12bot (Talk | contribs)
 
 
 
Defined in header <algorithm>
template< class RandomAccessIterator >
void random_shuffle( RandomAccessIterator first, RandomAccessIterator last );
(1)
template< class RandomAccessIterator, class RandomNumberGenerator >

void random_shuffle( RandomAccessIterator first, RandomAccessIterator last,
                     RandomNumberGenerator& r );

template< class RandomAccessIterator, class RandomNumberGenerator >
void random_shuffle( RandomAccessIterator first, RandomAccessIterator last,

                     RandomNumberGenerator&& r );
(2) (until C++11)



(since C++11)
template< class RandomAccessIterator, class UniformRandomNumberGenerator >

void shuffle( RandomAccessIterator first, RandomAccessIterator last,

              UniformRandomNumberGenerator&& 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.

1) The random number generator is implementation-defined, the function std::rand is often used.

2) The random number generator is the function object r.

3) The random number generator is the function object g.

Contents

Parameters

first, last - the range of elements to shuffle randomly
r - function object returning a randomly chosen value of type iterator_traits<RandomAccessIterator>::difference_type in the interval [0,n) if invoked as r(n)
g - function object returning a randomly chosen value of type UniformRandomNumberGenerator::result_type in the interval [g.min(), g.max()] if invoked as g() (intended to be used with uniform random number generators from the standard library)

Return value

(none)

Complexity

linear in the distance between first and last

Possible implementation

First version
template<class RandomAccessIterator, class RandomNumberGenerator>
void random_shuffle(RandomAccessIterator first, RandomAccessIterator last, 
                    RandomNumberGenerator&& r)
{
    typename std::iterator_traits<RandomAccessIterator>::difference_type i, n;
    n = last - first;
    for (i = n-1; i > 0; --i) {
        std::swap(first[i], first[r(i+1)]);
    }
}
Second version
template<class RandomAccessIterator, class UniformRandomNumberGenerator>
void shuffle(RandomAccessIterator first, RandomAccessIterator last, 
             UniformRandomNumberGenerator&& g)
{
    typedef typename std::iterator_traits<RandomAccessIterator>::difference_type diff_t;
    typedef typename std::make_unsigned<diff_t>::type udiff_t;
    typedef typename std::uniform_int_distribution<udiff_t> distr_t;
    typedef typename distr_t::param_type param_t;
 
    distr_t D;
    diff_t n = last - first;
    for (diff_t i = n-1; i > 0; --i) {
        std::swap(first[i], first[D(g, param_t(0, i))]);
    }
}

Example

The following code randomly shuffles the integers 1..10

#include <random>
#include <algorithm>
#include <iterator>
#include <iostream>
 
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);
 
    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

See also

generates the next greater lexicographic permutation of a range of elements
(function template) [edit]
generates the next smaller lexicographic permutation of a range of elements
(function template) [edit]