生成互不相同随机数的两种算法
2011-11-07 18:13
381 查看
第一种方法
如何产生不重复的随机数?最容易想到的方法,是逐个产生这些随机数,每产生一个,都跟前面的随机
数比较,如果重复,就重新产生。这是个很笨的方法,且比较次数呈线性增长,越往后次数越多。其实这些
比较是多余的,完全可以不进行比较,只要反过来,按顺序产生这些数,但随机产生它们的位置。例如下
面产生100个100以内不重复随机数的代码:
int a[100];
for(i=0; i<=99; ++i) a[i]=i;
for(i=99; i>=1; --i) swap(a[i], a[rand()%i]);
上面这段代码只需要遍历一次就可以产生这100个不重复的随机数,它是如何做到的呢?首先第二行按顺
序用0到99填满整个数组;第三行,是随机产生从0到m-2个数组下标,把这个下标的元素值跟m-1下标的元
素值交换,一直进行到下标为1的元素。因此它只需要遍历一次就能产生全部的随机数。
再看下面的代码,原理跟上面例子相似,但效率比上面的差点,但仍不失为一个好方法:
int a[100]={0};
int i, m;
for(i=1; i<=99; ++i)
{
while(a[m=rand()%100]);
a[m] = i;
}
这段代码也是随机产生位置,但它预先把整个数组初始化为0,然后随机产生其中一个位置,如果该元素
值为0,表示这个位置还没有被使用过,就把i赋予它;否则,就重新随机产生另一个位置,直到整个数组
被填满。这个方法,越到后面,遇到已使用过的元素的可能性越高,重复次数就越多,这是不及第一个方
法的地方,但总的来说,效率还是不错的。
这种方法的缺点 是不能产生大于M的随机数(M<=N)
第二种方法
一、动态生成一个数组,其长度是要产生随机数的上界,每个元素的值为其对应的下标。
二、随机生成该范围内的一个数,以该数为数组下标,取出对应的数组中的元素(其实数组中的元素和该随机数一样),取出后,将下标对应的数组元素赋值为-1(赋值-1是因为随机数中或许有0),来作为下次判断的依据。
三、再产生该范围内的随机数,如果对应的数组下标中的元素是-1,就再生成,直到不是-1为止。
四、重复步骤二、三,直到产生够所需的随机数个数。
注意点:随机数个数应小于等于随机数的范围
具体的代码如下:
view plaincopy
to clipboardprint?
void RandomNumbers(int limit,int sum)
{
fstream file("data.txt",ios::out);
int count=0,number=0;
int *temp=new int[limit];
for(int i=0;i<limit;i++)
{
temp[i]=i;
}
srand(static_cast<unsigned int>(time(NULL)));
for(int i=1;i<=sum;i++)
{
number=rand()%limit;
while(temp[number]==-1)
{
number=rand()%limit;
}
file<<temp[number]<<"\t";
count++;
if(count%10==0)
{
file<<endl;
}
temp[number]=-1;
}
delete []temp;
temp=NULL;
file.close();
cout<<"已产生"<<sum<<"个"<<"大于等于0少于"<<limit<<"的互不相等的随机数"<<endl;
}
该函数实现的是产生0~limit(包括0和limit)内的sum个随机数。
如何产生不重复的随机数?最容易想到的方法,是逐个产生这些随机数,每产生一个,都跟前面的随机
数比较,如果重复,就重新产生。这是个很笨的方法,且比较次数呈线性增长,越往后次数越多。其实这些
比较是多余的,完全可以不进行比较,只要反过来,按顺序产生这些数,但随机产生它们的位置。例如下
面产生100个100以内不重复随机数的代码:
int a[100];
for(i=0; i<=99; ++i) a[i]=i;
for(i=99; i>=1; --i) swap(a[i], a[rand()%i]);
上面这段代码只需要遍历一次就可以产生这100个不重复的随机数,它是如何做到的呢?首先第二行按顺
序用0到99填满整个数组;第三行,是随机产生从0到m-2个数组下标,把这个下标的元素值跟m-1下标的元
素值交换,一直进行到下标为1的元素。因此它只需要遍历一次就能产生全部的随机数。
再看下面的代码,原理跟上面例子相似,但效率比上面的差点,但仍不失为一个好方法:
int a[100]={0};
int i, m;
for(i=1; i<=99; ++i)
{
while(a[m=rand()%100]);
a[m] = i;
}
这段代码也是随机产生位置,但它预先把整个数组初始化为0,然后随机产生其中一个位置,如果该元素
值为0,表示这个位置还没有被使用过,就把i赋予它;否则,就重新随机产生另一个位置,直到整个数组
被填满。这个方法,越到后面,遇到已使用过的元素的可能性越高,重复次数就越多,这是不及第一个方
法的地方,但总的来说,效率还是不错的。
这种方法的缺点 是不能产生大于M的随机数(M<=N)
第二种方法
一、动态生成一个数组,其长度是要产生随机数的上界,每个元素的值为其对应的下标。
二、随机生成该范围内的一个数,以该数为数组下标,取出对应的数组中的元素(其实数组中的元素和该随机数一样),取出后,将下标对应的数组元素赋值为-1(赋值-1是因为随机数中或许有0),来作为下次判断的依据。
三、再产生该范围内的随机数,如果对应的数组下标中的元素是-1,就再生成,直到不是-1为止。
四、重复步骤二、三,直到产生够所需的随机数个数。
注意点:随机数个数应小于等于随机数的范围
具体的代码如下:
view plaincopy
to clipboardprint?
void RandomNumbers(int limit,int sum)
{
fstream file("data.txt",ios::out);
int count=0,number=0;
int *temp=new int[limit];
for(int i=0;i<limit;i++)
{
temp[i]=i;
}
srand(static_cast<unsigned int>(time(NULL)));
for(int i=1;i<=sum;i++)
{
number=rand()%limit;
while(temp[number]==-1)
{
number=rand()%limit;
}
file<<temp[number]<<"\t";
count++;
if(count%10==0)
{
file<<endl;
}
temp[number]=-1;
}
delete []temp;
temp=NULL;
file.close();
cout<<"已产生"<<sum<<"个"<<"大于等于0少于"<<limit<<"的互不相等的随机数"<<endl;
}
该函数实现的是产生0~limit(包括0和limit)内的sum个随机数。
相关文章推荐
- 生成互不相同随机数的一种算法
- 生成互不相同随机数的一种算法
- 生成互不相同随机数的一种算法
- [算法][随机数]一种生成2个不相同的随机数的方法
- 生成k个小于n的互不相同的随机数
- C#在一段数字区间内随机生成若干个互不相同的随机数
- 生成k个小于n的互不相同的随机数
- 生成一定范围内的互不相同的随机数的方法比较
- 生成互不相同的N个随机数
- 生成一定范围内的互不相同的随机数的方法比较
- C#生成指定数目的互不相同的随机数(转)
- C#在一段数字区间内随机生成若干个互不相同的随机数
- 生成互不相同的随机数
- C#生成指定数目的互不相同的随机数
- C#生成互不相同随机数的实现方法
- C#生成指定数目的互不相同的随机数
- 用C#生成足够随机的互不相同的随机数
- 生成k个小于n的互不相同的随机数
- 用C#生成足够随机的互不相同的随机数
- 随机系列生成算法(随机数生成)