1. 问题
给定一个数据流,数据流的长度 N N N未知,要求从中选择 m m m个数,每个数字被选择的概率都是 m N \frac{m}{N} Nm
2. 做法
有一个算法可以用于解决上述问题,该算法名称是蓄水池抽样算法。
算法的步骤如下:
- 若接收的数据流的长度小于 m m m,则直接把接收的数据放入蓄水池中。
- 当接收到第
i
i
i个数据时,
i
≥
m
i \ge m
i≥m,在区间
[
0
,
i
)
[0,i)
[0,i)中生成一个随机数
random
。若random < m
,就替换把第random
个蓄水池中的数据替换为第i
个数据。 - 重复步骤2,直到处理完所有的数据。
3. 原理
4. 代码
4.1 生成随机数的方法
4.1.1 生成一个随机数
cout << rand() << endl;
4.1.2. 生成区间[a,b)一个随机数
cout << (rand() % (b - a)) + a << endl;
4.2 蓄水池抽样算法的代码
int cnt = 0;
int arr[m] = {};
while(cin >> x){
if(cnt < m) arr[cnt] = x;
else{
int addr = rand() % (cnt + 1); // 生成一个随机数
if(addr < m) arr[addr] = x;
}
++ cnt;
}