蓄水池算法

蓄水池算法

今天在群里看到这么一道题,读取一个未知行数的文件,随机输出一行,并保证输出的每行概率相等,这道题应当采用蓄水池算法,非常神奇的算法,巧妙的利用了概率连乘的方法使得概率相等,具体的原理可以参考 戳这里这种方法感觉充分利用了当前的信息与迭代的思想,非常巧妙! 以下是我的实验代码:

 1 #include<stdio.h>
 2 #include<time.h>
 3 #include<stdlib.h>
 4 #include<iostream>
 5 using namespace std;
 6 
 7 void swap_a(int *a,int *b)
 8 {
 9     int temp ;
10     temp = *a;
11     *a = *b;
12     *b = temp;
13 
14 }
15 // swap by  xor
16 void swap_b(int *a,int *b)
17 {
18     *a = *a^*b;
19     *b = *a^*b;
20     *a = *a^*b;
21 }
22 void randomint(int a[],int _range,int _length)
23 {
24     if(_length<=0) return;
25     for(int i = 0; i < _range;++i)
26     {
27         a[i]=(rand()%_range);
28     }
29 }
30 int reservoirsampling(int a[],int end)
31 {
32     int i = 1;
33     int ans =a[0];
34     while(a[i]!=end){
35        if(rand()%i==1) ans = a[i];
36        i++;
37     }
38     return ans;
39 
40 }
41 void reservoirsamplingk(int a[],int _length,int _k)
42 {
43     if(_k>_length) return;
44     for(int i = _k; i<_length; i++){
45         int temp = rand()%i;
46         if(temp<_k)
47         {
48             swap_b(&a[i],&a[temp]);
49         }
50     }
51 }
52 int main()
53 {
54     //随机产生了一个长度为1000,范围在10000内的随机数组
55     //其中随机抽取了一个数字作为结束符位置为counts,在
56     //遍历一遍的清况下已概率为1/counts输出结束符之前的
57     //任意一个数字
58     //@蓄水池算法:读入一个随机长度为n的数组或者文件,
59     //遍历一遍,以n分之1输出某一行或者一个数,具体的实
60     //现方法就为以1/i确定是否将当前数(行)作为输出,i
61     //为当前循环次数。
62     //@蓄水池算法应用2:在一个长度为n(n是提前不知道的)
63     //的数组里,以概率为k/n选取k个数。或者说,在一个未
64     //知或者很大样本空间内随机选取n个数:
65     //具体方法:首先前k个数,在下次循环时,以k/i的概率
66     //确定是否与前k个数中的某个数是否与当前数替换
67     int ans,counts,end;
68     int length = 1000;
69     int range = 10000;
70     int *a = new int[1001];
71     randomint(a,length,range);
72     counts = rand()%1000;
73     end = a[counts];
74     ans = reservoirsampling(a,end);
75     cout<<"以概率为"<<counts<<"分之一选取了数字:"<<ans<<endl;
76     for(int i=0;i<10;i++)
77         cout<<a[i]<<endl;
78     cout<<"////////////////////////////\n"<<endl;
79     reservoirsamplingk(a,length,10);
80      for(int i=0;i<10;i++)
81         cout<<a[i]<<endl;
82     delete [] a;
83     return 0;
84 }

最近打算阅读下redis的源代码,据说实现的很优美,并且有很多也很有帮助,顺便学学数据库~ 后面可能会更一些最近项目上学到的东西,在研究GraphCut中……



Previous     Next
SureD /
Published under (CC) BY-NC-SA in categories algorithm  tagged with algorithm 
分享到: 更多
>