简介
生成一个随机数是很多时候需要实现的,往往会使用rand函数的方式,如下所示。
#include <iostream>
using namespace std;
int main()
{
int i = rand();
printf("%d", i);
return 0;
}
这种直接使用rand函数去获取随机数的方式由于使用了默认的随机种子,所以获得的随机数都是同一个值。此时一般会采取使用时间种子的方法,因为时间每时每刻都是不同的,所以每次获得的随机数就是不同的。如下所示。
#include <iostream>
#include<ctime>
using namespace std;
int main()
{
srand(time(0));//srand设置随机种子,time(0)获取当前时间戳
int i = rand();
printf("%d", i);
return 0;
}
但是当要在一定范围内获取随机数的时候,这个方法就不能用了,就有可能会出现获取到重复数字的情况。如下所示获取10以内的随机数,对rand的值进行取模。
#include <iostream>
#include<ctime>
using namespace std;
int main()
{
srand(time(0));
int i = rand()%10;//模上取值范围
printf("%d", i);
return 0;
}
获取不重复随机数
这个时候就不能再单纯的使用rand函数来进行取值,需要使用到一些数据结构。在这里我使用了链表,也可以使用vector实现,两者区别在于时间复杂度,当取值范围较大时,使用vector效率更高,当范围较小时,使用list更简单高效。
思路:
1.把取值范围依次放入一个链表中;
2.使用时间种子rand并取模(模上链表长度),获得一个随机值index;
3.获取链表中index位置的值,这个值即最终取出的随机值;
4.删除链表中的被取到值。
如下图所示。
代码实现如下。
#include <list>
#include <iostream>
#include<ctime>
using namespace std;
int GetListValue(list<int>* l, int index)
{
list<int>::iterator iter;
int i = 0;
for (iter = l->begin(); ++i < index; iter++)
{
}
i = *iter;
l->erase(iter);
return i;
}
int GetRandNum(list<int>* l)
{
srand(time(0));
int s = l->size();
int index = rand() % s;
int res = GetListValue(l, index);
return res;
}
int main()
{
list<int> DataList = {};
int num = 10;
for (int i = 0; i < num; i++)
{
DataList.push_back(i);
}
for (int i = 0; i < num; i++)
{
int tmp = GetRandNum(&DataList);
printf("%d\n", tmp);
}
return 0;
}