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
Определено в заголовке <algorithm>
template < class RandomIt >
void random_shuffle ( RandomIt first, RandomIt last ) ;
(1) (устарело в C++14)
(удалено в C++17)
(2)
template < class RandomIt, class RandomFunc >
void random_shuffle ( RandomIt first, RandomIt last, RandomFunc & r ) ;
(до C++11)
template < class RandomIt, class RandomFunc >
void random_shuffle ( RandomIt first, RandomIt last, RandomFunc && r ) ;
(начиная с C++11)
(устарело в C++14)
(удалено в C++17)
template < class RandomIt, class URBG >
void shuffle ( RandomIt first, RandomIt last, URBG && g ) ;
(3) (начиная с C++11)

Переупорядочивает элементы в заданном диапазоне [ first , last ) таким образом, что каждая возможная перестановка этих элементов имеет равную вероятность появления.

1) Источник случайности определяется реализацией, но функция std::rand часто используется.
2) Источником случайности является функциональный объект r .
Если выполняется любое из следующих условий, поведение не определено:
  • Тип возвращаемого значения r не конвертируется в std:: iterator_traits < RandomIt > :: difference_type .
  • Для положительного значения n типа std:: iterator_traits < RandomIt > :: difference_type , результат r ( n ) не является случайно выбранным значением в интервале [ 0 , n ) .
3) Источником случайности является объект g .
Для типа T , заданного как std:: remove_reference_t < URBG > , если выполняется любое из следующих условий, поведение не определено:
(до C++20)

Если тип * first не является Swappable (до C++11) RandomIt не является ValueSwappable (начиная с C++11) , поведение не определено.

Содержание

Параметры

first, last - пара итераторов, определяющая диапазон элементов для случайного перемешивания
r - функциональный объект, возвращающий случайно выбранное значение
g - объект-генератор, возвращающий случайно выбранное значение
Требования к типам
-
RandomIt должен удовлетворять требованиям LegacyRandomAccessIterator .

Сложность

Ровно std:: distance ( first, last ) - 1 обменов.

Возможная реализация

Смотрите также реализации в libstdc++ и 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))]);
    }
}

Примечания

Обратите внимание, что реализация не регламентирована стандартом, поэтому даже если вы используете точно такую же RandomFunc или URBG (Uniform Random Number Generator), вы можете получить разные результаты в разных реализациях стандартной библиотеки.

Причина удаления std::random_shuffle в C++17 заключается в том, что версия только с итераторами обычно зависит от std::rand , которая теперь также рассматривается для устаревания. ( std::rand следует заменить классами из заголовка <random> , поскольку std::rand считается вредной .) Кроме того, версия std::random_shuffle только с итераторами обычно зависит от глобального состояния. Алгоритм перемешивания std::shuffle является предпочтительной заменой, поскольку он использует URBG в качестве своего третьего параметра.

Пример

Случайным образом перемешивает последовательность [ 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';
}

Возможный вывод:

8 6 10 4 2 3 7 1 9 5

Отчёты о дефектах

Следующие отчеты об изменениях поведения, влияющие на дефекты, были применены ретроактивно к ранее опубликованным стандартам C++.

DR Применяется к Поведение как опубликовано Корректное поведение
LWG 395 C++98 источник случайности для перегрузки (1) не был указан, и
std::rand не мог быть источником из-за требований C библиотеки
определяется реализацией,
и использование std::rand разрешено
LWG 552
( N2423 )
C++98 r не требовался в качестве источника
случайности для перегрузки (2) [1]
требуется
  1. Перегрузка (3) имеет тот же недостаток, но эта часть решения не применима к C++98.

Смотрите также

генерирует следующую большую лексикографическую перестановку диапазона элементов
(шаблон функции)
генерирует следующую меньшую лексикографическую перестановку диапазона элементов
(шаблон функции)
случайным образом переупорядочивает элементы в диапазоне
(функциональный объект алгоритма)