zoukankan      html  css  js  c++  java
  • 从十名观众中随机选取8名幸运观众,不能重复选取同一个观众为幸运观众(CPrimerPlus第十六章第五题)

    其实就是CPrimerPlus第十六章第五题,只不过我把标题写的更生动些啦。

    刚开始我理解两次选的人不一样就行了,于是只安排了连续两次选人之间对比,人相同了那么就将第二次选择作废,重来一次,直到选的人不同才采用,这时计数器加1(计数器达到8就停止)。

    当然,这种方法是不符合题意的,因为第二次选的幸运观众不会和第一次选的相同,但是第三次可以和第一次相同啊。这样就会有幸运观众多次被选中了。

    void RandPrint1(int * p, int size, int num)    //p是int数组,可理解为观众的标号(1-10);size表示观众的总数量(10);num表示要抽取的幸运观众的数量(比如是8)。
    {
        int i=0;
        int PreRand=-1;
        int Rand;
    
        srand((unsigned) time(NULL)); //用时间做种,每次产生随机数不一样for(i=0; i<num; )  //成功抽取的幸运观众的人数达到8就停止
        {
            Rand=((int)rand() % size);
            if(Rand != PreRand)  //抽取的幸运观众号码与上一个幸运观众号码不同,即两个幸运观众不是同一个人
            {
                printf("%d ", *(p+Rand));
                i++;
            }
            PreRand = Rand;  //这个幸运观众下一轮抽取中就变成了“上一个幸运观众”咯
        }
    }

    第二种方法的话,采用选一个幸运观众,就把他从候选人名单中剔除,免得再选中。而且越选越少,越选越简单明了。就是把存着观众号码的内存不断的移动,覆盖掉已经备选的观众的号码,在剩下的(所有观众数 - 被选观众数)的观众中继续选择幸运观众。

    思路可以参见下图:

    void RandPrint2(int * p, int size, int num)
    {
        int Rand;
        int i;
        srand((unsigned) time(NULL));
    
        for(i=0; i<num; i++)
        {
            Rand = (int)rand() % size;
            printf("%d ", *(p+Rand));
            memcpy(p+Rand, p+Rand+1, (size-Rand-1)*sizeof(int));    //内存中一块内容的复制
            size--;    //选一个就踢出去,从剩下的里面选取幸运观众,这已经被“踢出去”的幸运观众就不会被再次选中了。
        }
    }

    好了,简单的一道题解释了半天,自己也是够啰嗦的了。

    一个简单的程序测试这两个函数,如下   (其实这个没什么含义,只是占点篇幅而已,大可不看):

    // 从一个数组中挑选出指定个数的元素,这些元素是随机选取的,并且不能重复,类似于抽取几名幸运观众
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
                                                                                                                                                                                                                                                                                                                                                  
    void RandPrint1(int *, int, int);
    void RandPrint2(int *, int, int);
    
    int main(void)
    {
        int candidates[10] = {1,2,3,4,5,6,7,8,9,10};
        RandPrint1(candidates,10,8);
        printf("
    RandPrint 1 version is Done!
    ");
        RandPrint2(candidates,10,8);
        printf("
    RandPrint 2 version is Done!
    ");
    
        return 0;
    }
    
    void RandPrint1(int * p, int size, int num)    //这只能保证不连续抽到相同的幸运观众,不能保证抽到的所有幸运观众都不同。
    {
        int i=0;
        int PreRand=-1;
        int Rand;
    
        srand((unsigned) time(NULL)); //用时间做种,每次产生随机数不一样
    
        if(size < num)
        {
            printf("numbers is bigger than size, break!
    ");
            exit(-1);
        }
    
        for(i=0; i<num; )
        {
            Rand=((int)rand() % size);
            if(Rand != PreRand)
            {
                printf("%d ", *(p+Rand));
                i++;
            }
            PreRand = Rand;
        }
    }
    
    void RandPrint2(int * p, int size, int num)
    {
        int Rand;
        int i;
    
        for(i=0; i<num; i++)
        {
            srand((unsigned) time(NULL));
            Rand = (int)rand() % size;
            printf("%d ", *(p+Rand));
            memcpy(p+Rand, p+Rand+1, (size-Rand-1)*sizeof(int));    //内存中一块内容的复制
            size--;    //选一个就踢出去,从剩下的里面选取幸运观众,这已经被“踢出去”的幸运观众就不会被再次选中了。
        }
    }
  • 相关阅读:
    java内部类
    接口与继承
    数据结构
    数据I/O流
    课程总结
    第六次实训作业异常处理
    常用类的课后作业
    窗口实训1
    实训作业4
    实训作业3
  • 原文地址:https://www.cnblogs.com/TomLily/p/7054695.html
Copyright © 2011-2022 走看看