基于实验六对基于时间抽取随机不同数的算法研究

Posted nnn13579

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于实验六对基于时间抽取随机不同数的算法研究相关的知识,希望对你有一定的参考价值。

实验报告链接:

https://www.cnblogs.com/nnn13579/p/10992122.html

 

对于基于时间抽取不同数,容易出现:

技术图片

 

这是某位同学的实验结果。

当中使用了这样的语句:

srand((unsigned)time(NULL));

和下面这条是一个效果:

srand((int)time(0));

问题就出在这里。

原因很简单,计算机运算速度很快,精确到秒对于计算机来说太大了。

那么将int改成double是否有效解决呢?

No,除非你用的是Linux系统的php,精确到毫秒。

而且当要抽的量大时,也可能重复。

所以我的第一想法是,当重复时,直接全部重抽好了。

所以有了如下代码:

 1     int k=0;
 2     do
 3         srand((int)time(0));
 4         for(int i=0;i<n;i++)
 5             luck[i]=rand()%num;
 6         for(int i=0;i<n;i++)
 7             for(int j=i+1;j<n;j++)
 8                 if(luck[i]==luck[j])
 9                     k=1;break;
10                 
11     while(k);

 

通过检测是否有抽出了相同数来确定是否重抽。

但显然,这种做法效率低下。

于是考虑在抽出相同数时,反复更改抽出的数来确保没有相同数。

于是:

 1 for(int i=0;i<n;i++)
 2     srand((double)time(0));
 3     luck[i]=rand()%num;
 4     int j=0,k=0;
 5     for(;j<i;j++)
 6         if(luck[i]==luck[j])
 7             k=1;
 8             while(k)
 9                 srand((double)time(0));
10                 luck[i]=rand()%num;
11                 if(luck[i]!=luck[j]) 
12                     int t=0;
13                     for(;t<i;t++)
14                         if(luck[t]==luck[i]) break;
15                     if(t==i) k=0;
16                 
17             
18         
19 

 

但是,当抽40人时,起码要40+s,

效率低下的问题依旧没有解决。

那么优化算法,利用C(n)(m)=C(m-n)(m),增添以下内容:

 1  if(n<=num/2||n<=num/2+1)
 2         fun1(luck,n,date,num);
 3         fun2(luck,n);
 4     
 5     else
 6         int tluck[num-n];
 7         fun1(tluck,num-n,date,num);
 8         fun2(tluck,num-n);
 9         int tluckn=0,luckn=0;
10         for(int i=0;i<n;i++)
11             while(luckn==tluck[tluckn])
12                 luckn++;
13             luck[i]=luckn;
14             luckn++;
15         
16     

 

fun1()为抽取随机数的函数,fun2()为排序抽取的数。

但这治标不治本。

问题在哪里呢?

出在会抽出重复数。

对于抽n个数,极大可能抽了不止n次。

于是我有了一个想法,把抽过的数全部排除掉,然后在剩下数中抽取。

 1 void fun1(int luck[],int n,int num,int i,int all[])
 2     if(i<n)
 3         srand((double)time(0));
 4         int t=rand()%num;
 5         luck[i]=all[t];
 6         for(int j=t;j<num-1;j++)
 7             all[j]=all[j+1];
 8         fun1(luck,n,num-1,i+1,all);
 9     
10 
11 ……
12 ……
13 ……
14 int all[num];
15 for(int i=0;i<num;i++)
16     all[i]=i;
17 fun1(luck,n,num,0,all);

 

all[]用于存储所有人的序号,

每个人的序号都有两种,

一种是在班里的序号,

另一种是在数组中的“房间号”。

而我们每次抽的都是房间号。

每次抽一个人后,将这个人踢掉,然后剩下的人一次向前移一个“房间”填补空位,实现房间里的人更新。

之后再用抽剩的人去抽下一轮。

由于

int t=rand()%num;

中,num值一直在变,随机的数也会一直变化,实现刷新。

即便一直抽取同一个“房间”,例如1号房,

但由于房间里的人已经换过了,所以不会是抽出同一人。

经过这次算法优化,能够实现抽n人只需要抽n次,抽取40人的时间压缩到了1s内。

以上是关于基于实验六对基于时间抽取随机不同数的算法研究的主要内容,如果未能解决你的问题,请参考以下文章

基于随机森林算法的糖尿病数据集回归

基于随机森林算法的人脸数据集分类

秒懂算法 | 基于主成分分析法随机森林算法和SVM算法的人脸识别问题

基于随机接入代价的异构网络速率分配算法研究

基于莱维飞行和随机游动策略改进灰狼算法matlab代码

基于mykernel的一个简单的时间片轮转多道程序内核代码分析