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;}