您的位置:首页 > 其它

生成互不相同随机数的两种算法

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个随机数。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: