产生n个不重复的随机数

一.去重法

       这是最容易想到的方法,逐个产生这些随机数,每产生一个,都跟前面的随机数比较,如果重复,就重新产生。可以使用hashtable或数组标记,这种方法效率比较低,且比较次数呈线性增长,越往后次数越多。

二.筛选法

       所谓“筛选法”就是根据要产生随机数指定的范围(起始数必须小于终止数),将这些数全部装入一个数组,然后利用系统随机函数(比如 Random )随机产生一个下标,将这个下标对应的数值返回并删除对应的这个数,直到这个数组为空。 

该算法效率相对还是比较低,我们知道如果要删除一个数组元素,我们需要把这个数组元素后面的所有元素都向前移动1,这个移动操作是非常耗时的,这个算法慢就慢在这里。到这里,可能有人要说了,那我们不用数组,用链表,那删除不就很快了吗?没错,链表是能解决删除元素的效率问题,但查找的速度又大大降低了,无法像数组那样根据数组元素下标直接定位到元素。所以用链表也是不行的。

三.置换法(洗牌算法)

#include <stdlib.h>
#include <time.h>
#include <stdio.h>

int main()
{
    int i, k, end, n = 20;
    int arr[20];

    for(i = 0; i < n; i++)
        arr[i] = i+1;

    srand((unsigned)time( NULL ) );     //以系统时间作为种子

    end = n-1;                          // 有效数组末尾下标
    for(i = 0; i < n; i++)
    {
        k = rand()%(end+1);             // k表示数组下标
        printf("%d ",arr[k]);
        arr[k] = arr[end];              //将数组最后一个元素存入使用过的元素
        end--;
    }
}

      上面这段代码只需要遍历一次就可以产生这20个不重复的随机数,它是如何做到的呢?首先第二行按顺序用0到19填满整个数组;第三行,是随机产生从0到end个数组下标,把这个下标的元素值跟end下标的元素值交换,一直进行到下标为0的元素。因此它只需要遍历一次就能产生全部的随机数。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值