如何获取一定范围内不重复的随机数

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/MBuger/article/details/81450599

简介

生成一个随机数是很多时候需要实现的,往往会使用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;
}

猜你喜欢

转载自blog.csdn.net/MBuger/article/details/81450599