图片参考来自:
作者:阿凡卢
出处:http://www.cnblogs.com/luxiaoxun/
题型1:为下面题二的特例
在不知道文件总行数的情况下,如何从文件中随机的抽取一行,并且每行被抽中的
概率相等?即n的数量未知的情况下,还的确保每个数取的概率一样!这种方式主要实现在流数据!!证明如上面!
另一种,为此题的变种,可以带权值,求解方法一样,每次替换的概率只需为当前wi/(w当前总) -- wi为第i个的权值,w当前总为从开始到i的权值总和
被选中概率:
不被选择概率:
第i个的权值概率:
详细见此文:http://www.gocalf.com/blog/weighted-random-selection.html(以上公式借鉴于此文!)
题二:
此题为蓄水池抽样问题,保证n个数据取k 个,的概率仍为k/n!
#include <iostream>
#include <cassert>
#include <cstdlib>
#include <ctime>
#include <cstring>
using namespace std;
int rand_5();
int rand_4();
int find_n(int n);
int main()
{
srand((unsigned int)time(NULL));//不能放在函数内,只能用一次!
int count[5] = {0,0,0,0,0};
int find_arr[10];
memset(find_arr,0,sizeof(int)*10);
for (int i = 0;i < 10000 ;i++)
{
count[rand_5()] ++;
find_arr[find_n(10)]++;
}
for (int i = 0;i < 5 ;i++)
{
cout<<count[i]<<" ";
}
cout<<endl;
for (int i = 0;i < 10 ;i++)
{
cout<<find_arr[i]<<" ";
}
cout<<endl;
return 0;
}
int rand_5()//rand3 产生 rand5
{
int num;
do
{
num = 3*(rand()%3) + rand()%3;
} while (num >= 5);
return num ;
}
int rand_4()//rand5 -- 》》 rand_4
{
int num;
do
{
num = rand()%5;
} while (num >= 4); //丢弃
return num;
}
int find_n(int n)//n个找一个数 1/n的概率,前提不知道n的总大小情况,返回值为索引
{
int count = 1;//不能为0
int select = 0;
while( count <= n)//此处只是退出一个条件,实际情况不知道n大小,特别是流对象
{
if (rand()%count == 0)
{
select = count;
}
count++;
}
return select-1;
}
结果如下:总体分布比较均匀!