辅助函数,randint(i,j)获取[i,j]的一个随机数
int randint(int i , int j)
{
return rand()%(j-i+1)+i;
}
方法1:
从n个中取m个,当前这个数被取出的概率为n/m,即if(rand() % n < m)就被取出。
void genKnuth(unsigned int n , unsigned int m)
{
int remain = n;
int unselect = m;
for (int i = 0;i<n;++i)
{
if (rand()%remain < unselect)
{
std::cout<<i<<std::endl;
--unselect;
}
--remain;
}
}
剩下remain个数,还有unselect个未取,那么当前这个数被取出的概率为unselect/remain。要说的是从100个取20个数,这个方法必定能取出20个数。如果当前取出的以足20个,那么unselect=0,那么后面的所有数都不会被取。如果未满20个,那么后面的都有一定的概率被取到,极端情况就是前面都没有被取到,那么后面的数被取到的概率会越来越大,直到被取出的概率为1为止。
方法2:
向set中插入不重复的m个数即可。
void genSet(unsigned int n , unsigned int m)
{
std::set<int> s;
while(s.size() < m)
s.insert(rand() % n);
for (int i : s)
{
std::cout<<i<<std::endl;
}
}
set的特点是如果有了数字t,那么再插入数字t,也只是只有一个数字t。这点和MultiSet不同。不知道的可以学习下STL。
方法3:
把牌洗乱,然后抽出20个即可。
void genShuf(int n , int m)
{
int * x = new int[n];
for (int i = 0 ; i < n ; ++i)
{
x[i] = i;
}
int j;
for (int i = 0 ; i < m ; ++i)
{
j = randint(i , n-1);
if (i != j)
{
swap(x[i] , x[j]);
}
}
sort(x,x+m);
for (int i = 0 ; i < m ;++i)
{
std::cout<<x[i]<<std::endl;
}
delete []x;
}