Chinaunix首页 | 论坛 | 博客
  • 博客访问: 469065
  • 博文数量: 134
  • 博客积分: 3056
  • 博客等级: 中校
  • 技术积分: 1150
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-14 15:53
文章分类
文章存档

2013年(1)

2010年(133)

我的朋友

分类: C/C++

2010-11-10 17:08:45

「来源
《编程珠玑》习题1.4:如果认真考虑了习题3,你将会面对生成小于n且没有重复的k个整数的问题。最简单的方法就是使用前k个正整数。这个极端的数据集合将不会明显的改变位图方法的运行时间,但是可能会歪曲系统排序的运行时间。如何生成位于0至n - 1之间的k个不同的随机顺序的随机整数?尽量使你的程序简短高效。

「基本思想
基本思想:   
1. 获得小于n的随机数可以使用rand()%n获得,但既然是伪随机的,当然有可能重复; 
2. 利用洗牌的原理,将n个数(0至n-1)按次序排好,依次让每个数和一个随机挑选出的位子进行互换,这样肯定不会重复,而且次序被打乱,具有随机性。 只用交换k次,就可以取出k个小于n的互不相同的随机数。

「具体实现windows下(vc6.0, C语言)

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

#define N 20
#define K 10

void swap(int *a, int *b)
{
    *a ^= *b;
    *b ^= *a;
    *a ^= *b;
}

/******************************************************************************
*函数名称:void generateDiffRandV1(int a[], int n)
*函数功能:产生互不相同的随机数
*入口参数:
*返 回 值:无
*备 注:以空间换时间
*******************************************************************************/

void generateDiffRandV1(int a[], int n, int k)
{
    int i;
    time_t t;

    for (i = 0; i < n; i++){
        a[i] = i;
    }

    srand((int)time(&t));
    for (i = 0; i < k; i++){
        swap(&a[i], &a[i+rand()%(n-i)]);
    }
}

/******************************************************************************
*函数名称:void generateDiffRandV2(int a[], int n)
*函数功能:产生互不相同的随机数(产生随机数的范围是1~n-1)
*入口参数:
*返 回 值:无
*
*思 路:先生成一个放置座号的数组,然后从中随机抽取,抽取后为防止重复,立即归零。
* :每次生成座号,只需判断是否为0 即可,大大提高了程序执行的效率。
*******************************************************************************/

void generateDiffRandV2(int a[], int n)
{
    int *flag =(int *)malloc(sizeof(int) * n);
    static flag_once = 0;
    int i, index;
    
    for(i = 0; i < n; i++) flag[i] = i+1;
    if(!flag_once){
        srand(time(0));
        flag_once = 1;
    }
    
    for(i = 0; i < n;){
        index = rand() % n;
        if(flag[index] != 0){
            a[i++] = flag[index]-1;
            flag[index] = 0;
        }
    }
    free(flag);
}

void printArray(int a[], int n)
{
    int i;

    for (i = 0; i < n; i++){
        printf("%d ", a[i]);
    }
    printf("\n");
}

int main()
{
    int a[N];
    generateDiffRandV1(a, N, K);
    printArray(a, K);
    
    generateDiffRandV2(a, N);
    printArray(a, N);
    
    return 0;
}


「出错
为什么generateDiffRandV1()函数生成的随机数当中会有同时出现多个'0'?

问题解决了,swap函数不对,修正如下:

void swap(int *a, int *b)
{
    if (a != b){
        *a ^= *b;
        *b ^= *a;
        *a ^= *b;
    }
}

讨论见地址
阅读(4715) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~