编程珠玑:取样问题


1.问题描述

程序的输入包含两个整数m和n,其中m<n。输出是0~n-1范围内m个随机整数的有序列表,不允许重复。从概率的角度说,我们希望得到没有重复的有序选择,其中每个选择出现的概率相等。

 

2.解决思路与代码实现

编程珠玑上给出了四个函数

1).genknuth():算法依次考虑整数0,1,2,...,n-1,并通过一个适当的随机测试对每个整数进行选择。通过按序访问整数,可以保证输出结果是有序的

代码C++实现:

void genknuth(int m, int n) 
{
     for(int i = 0;i < 0;i++) 
     {
             if((bigrand() % (n-i)) < m)
             {
                    cout << i << "\n";
                    m--;
             }
     }
}

 

2).gensets():一种解决方案是在一个初始为空的集合里面插入随机整数,直到个数足够,这里利用C++ set容器

void gensets(int m, int n)
{
     set<int> S;
     
     while(S.size() < m)
           S.insert(bigrand() % n);
     set<int>::iterator i;
     
     for(i = S.begin(); i != S.end(); ++i)
           cout << *i << endl;
}

 

3).genshuffle():生成随机整数的有序子集的另一种方法是把包含整数0~n-1的数组的前m个元素打乱,然后把前m个元素排序输出。

void genshuf(int m, int n)
{
     int i,j;
     int *x = new int[n];
     
     for(i = 0; i < n; i++)
            x[i] = i;
     for(i = 0; i < m; i++)
     {
            j = randint(i, n-1);
            int t = x[i];
            x[i] = x[j];
            x[j] = t;
     }
     
     sort(x , x+m);
     for(i = 0; i < m; i++)
            cout << x[i] << endl;
}

 

4).genfloyd():m和n接近的时候,基于2)的改进,并能在m个步骤之内就可以按要求等概率地生成有序随机数

void genfloyd(int m, int n)
{
     set<int> S;
     set<int>::iterator i;
     
     for(int j = n-m; j < n; j++)
     {
             int t = bigrand() % (j+1);
             if(S.find(t) == S.end())
                 S.insert(t);            //t not in S 
             else
                 S.insert(j);            //t in S
     }
     
     for(i = S.begin(); i != S.end(); ++i)
             cout << *i << endl;
}

 

posted on 2012-08-15 16:00  as_  阅读(672)  评论(0编辑  收藏  举报

导航