C++
 Computer >> コンピューター >  >> プログラミング >> C++

【C++】STLで配列をシャッフルする方法:random_shuffleとshuffleの使い分けを解説

C++には、配列やコンテナの要素をランダムに並べ替えるための関数として、shufflerandom_shuffleが用意されています。これらの関数は配列だけでなく、vectorなどのコンテナにも同じ要領で使用できます。まずはrandom_shuffle()から見ていきましょう。

random_shuffle() 関数とは

random_shuffle()は、指定した範囲 [left, right) 内の要素をランダムに並べ替える関数です。各要素の位置を、ランダムに選ばれた別の位置と交換することで、要素をシャッフルします。

さらに、独自の乱数生成関数を引数として渡すことで、「どの位置の要素を選ぶか」を制御することも可能です。特に指定しない場合は、内部が持つデフォルトの乱数生成機能が使用されます。

コード例

#include <bits/stdc++.h>
using namespace std;
int myRandomGenerator(int j) {
   return rand() % j;
}
main() {
   srand(unsigned(time(0)));
   vector<int> arr;
   for (int j = 1; j < 20; ++j) // 1〜19の数値を生成してvector arrに追加
   arr.push_back(j);
   random_shuffle(arr.begin(), arr.end()); // 内蔵の乱数機能でシャッフル
   cout << "arr elements:";
   for (vector<int>::iterator i = arr.begin(); i != arr.end(); ++i)
   cout << ' ' << *i;
   cout << endl;
   // 独自のmyRandomGeneratorを使用
   random_shuffle(arr.begin(), arr.end(), myRandomGenerator);
   cout << "arr elements:";
   for (vector<int>::iterator i = arr.begin(); i != arr.end(); ++i)
   cout << ' ' << *i;
   cout << endl;
}

実行結果

arr elements: 5 14 15 6 3 16 13 12 10 2 4 1 17 9 18 11 7 8 19
arr elements: 8 10 5 6 14 1 15 3 19 16 13 18 7 9 4 12 11 17 2

shuffle() 関数とは

shuffle()も、指定した範囲 [left, right) 内の要素をランダムに並べ替えるための関数です。random_shuffle()との大きな違いは、引数として一様乱数生成器(uniform random number generator)を受け取る点にあります。

コード例

#include <bits/stdc++.h>
using namespace std;
main() {
   vector<int> arr;
   unsigned seed = 0;
   for (int j = 1; j < 20; ++j) // 1〜19の数値を生成してvector arrに追加
   arr.push_back(j);
   shuffle(arr.begin(), arr.end(), default_random_engine(seed));
   cout << "arr elements:";
   for (vector<int>::iterator i = arr.begin(); i != arr.end(); ++i)
   cout << ' ' << *i;
   cout << endl;
}

実行結果

arr elements: 19 7 5 6 12 4 13 3 1 17 11 14 18 2 8 15 9 10 16

random_shuffle() と shuffle() の違い

両者の唯一的な違いは、random_shuffle()rand()関数を使ってランダムなインデックスを生成するのに対し、shuffle()は一様乱数生成器を使用するという点です。なお、random_shuffle()に一様乱数生成器を渡せば、似たような結果を得ることも可能です。

補足: random_shuffle()はC++14で非推奨(deprecated)となり、C++17では標準ライブラリから削除されました。そのため現在のC++コードでは、<random>ヘッダが提供するstd::shuffle()を使用することが推奨されています。再現性のある結果が必要な場合はシード値を固定し、実行ごとに異なる結果が欲しい場合はrandom_deviceなどでシードを与えるとよいでしょう。

  1. C++で配列要素の移動だけで配列を均等化するために必要な操作回数を求める方法

    この記事では、n個の要素を持つ配列が与えられたとき、配列内の要素同士で値を受け渡すことによってすべての要素を同じ値に揃える(均等化する)ために必要な操作回数を求めるC++プログラムを紹介します。 ここでいう「1回の操作」とは、ある要素から値を1だけ引き、その分を別の要素へ1だけ加えることを指します。つまり減算と加算を合わせて1セットとしてカウントします。重要なのは、値の受け渡しによって配列全体の合計は常に変わらないという点です。 問題例 入力: arr[] = {4, 0, 3, 1, 2} 出力: 3 説明: 最終的にすべての要素が揃う値は「2」です。 arr[0] の値 4 から 2 を

  2. C++のSTLを使って配列が回文かどうかを判定するプログラム

    整数 n 個からなる配列 arr[n] が与えられたとき、「その配列は回文(パリンドローム)か?」を判定するのが本稿のテーマです。C++ の STL(標準テンプレートライブラリ)を活用して、この問題をシンプルに解いていきます。 STLとは STL(Standard Template Library)は、C++ に用意されたテンプレートクラスの集合体で、スタック・キュー・リストといったデータ構造や、ソート・反転などの便利な関数を提供します。これらを活用するには、テンプレートクラスに関する基本的な知識が必要です。本稿では、STL の reverse() 関数を使って配列を反転させています。 回文と