シャッフルアルゴリズムは、重複しない乱数を生成できるアルゴリズムの一つです。たとえば、10 個の乱数を生成し、そのすべてが「重複しない」必要があるとします。多くの人は、まず rand 関数で乱数を 1 つ取得して配列に格納し、配列にすでにある数字と比較する方法を思いつくと思います。この方法は簡単ですが、性能がとても悪くなります。ここで紹介するシャッフルアルゴリズムは、性能の面でその方法とは天と地ほどの差があります。シャッフルアルゴリズムの原理は実はとても単純で、まず配列に数字を入れ、その後に数字を打ち散らす(シャッフルする)というものです。
解説:
たとえば、10 個の重複しない乱数を生成したいとします。まず、配列を作成して 1~10 を格納します。
int x[10]={0};
for(int i=0;i<=9;i++){
x[i]=i; //配列 x の 1~10 の要素に順番にデータを入れる(例:x[1]=1, x[2]=2)
}つまり、x[0]=0、x[1]=1、x[2]=2……となります。
次に、交換法を使って配列のデータを打ち散らします。
time_t xx;
srand((unsigned)time(NULL)); //現在の時刻で乱数表を初期化する
for(int ii=0;ii<=1000;ii++){
int n1=rand()%10; //0~9 の乱数を生成する
int n2=rand()%10;
//配列のデータを交換する(打ち散らす)
int temp=x[n1];
x[n1]=x[n2];
x[n2]=temp;
}0~9 の乱数を生成して n1、n2 に代入し、x[n1] と x[n2] のデータを入れ替えます。
この動作をある回数(ここでは 1000 回と仮定します)繰り返すと、配列 x のデータは完全にばらばらになります。
つまり、x[0] に入っているのが必ずしも 0 とは限らず、x[1] に入っているのも必ずしも 1 とは限らなくなります。
これでアルゴリズムの説明は完了です。
配列の中身を出力すると、それは実質的に乱数になっていて、しかも数字が重複しません。
詳細なソースコード:
/*
洗牌演算法(シャッフルアルゴリズム)
重複しない乱数を生成する
座席の割り当てに使える
*/
#include
#include<stdlib.h> //乱数関数に必要
#include<time.h>
using namespace std;
int main()
{
int x[10]={0};
for(int i=0;i<=9;i++){
x[i]=i; //配列 x の 1~10 の要素に順番にデータを入れる(例:x[1]=1, x[2]=2)
}
time_t xx;
srand((unsigned)time(NULL)); //現在の時刻で乱数表を初期化する
for(int ii=0;ii<=1000;ii++){
int n1=rand()%10; //0~9 の乱数を生成する
int n2=rand()%10;
//配列のデータを交換する(打ち散らす)
int temp=x[n1];
x[n1]=x[n2];
x[n2]=temp;
}
for(int i=0;i<=9;i++){
cout<<x[i]<<endl; //出力
}
system("pause");
return 0;
}
プロジェクトファイルのダウンロード:Box.net|4Shared|Google|Dropbox
