一种随机抽题的简单算法,一种随机抽题的简单算法
【 tulaoshi.com - C语言心得技巧 】
一种随机抽题的简单算法
作者:贵州大学 王 凯
随机抽题是很多有关考试软件经常会遇到的问题,设相关题库中有n道题,要从中抽取m ( m<=n ) 道题,这要首先产生m个随机数。在C语言中,一般的做法是:
int *intArray;int i;time_t t;intArray = malloc(m*sizeof(int));/*time(&t)将获取当前时间,srand把当前时间作为随机数的种子*/srand((unsigned) time(&t));/*依次产生m个随机数*/for(i=0; i<m; i++) intArray[i] = rand() %n;……free(intArray);这样,就可以产生m个随机数,方法很简单,并且利用了当前时间作为随机数的种子,尽量地避免了出现重复抽题。但仔细一分析,重复抽题并未完全避免,同时是否已抽题不影响今后的抽取,将导致各个试题被抽取的几率不等。修正的方法有检查新抽取的题是否重复,若重复则重抽,这样做的方法很简单,仅仅在上面的程序中加入判断重复的语句,但各个试题被抽取的几率仍然不等。怎样办呢?
int *intArray;int i,j,k,temp;time_t t;intArray = malloc(m*sizeof(int));srand((unsigned) time(&t));/*依次产生m个随机数*/for(i=0; i<m; i++){ temp= rand() %n; /*查找temp原先的“真实”编号*/ for(j=0; j<i; j++) if(temp>= intArray[j])temp++; else{ /*temp应插在k位置处, 这样数组intArray就实现了排序,同时得到了temp原先的编号*/ k=j-1;break; } for(j=i-1;j>k;j--) intArray [j+1]= intArray [j]; intArray [k] =temp; ①/*以下根据题号产生题库部分省略*/……}free(intArray);上述做法的好处在于,没有任何附加存储空间,运算的复杂性大致上等于一个插入排序算法,但原始产生的题号顺序已经“被忽略了”,添加一个有m个元素的附加数组,就可以保留原始产生的题号顺序,例如intRandArray是一个有m个元素的附加数组,将①改为:
intRandArray[i] =intArray [k]= temp;如此我们就可以已很小的时间与空间代价,实现了无重复而且各个试题被抽取的几率相同的随机抽题算法。但C语言中rand()一直饱受垢病,专业人员一直寻求更好的随机数生成算法,这方面有很多参考资料,请读者查阅,本文不再赘述。读者可考虑将随机数生成算法整合到本文的随机抽题算法中,以获得更好的随机抽题算法。
来源:http://www.tulaoshi.com/n/20160129/1485312.html