• 蓄水池抽样算法应用


    从一个问题引出

    如何随机从n个对象中(这n个对象是按序排列的,但是在此之前你是不知道n的值的)随机选择一个对象?
    具体来说,如何在实现不知道文本文件行数的情况下读取该文件,从中随机选择并输出一行?

    这是《编程珠玑》中的一个习题,如果我们知道n的值,那么问题就可以简单的用一个大随机数rand()%n得到一个确切的随机位置,那么该位置的对象就是所求的对象,选中的概率是1/n。
    现在并不知道n的值,
    我们总是选择第一个对象,以1/2的概率选择第二个,以1/3的概率选择第三个,以此类推,以1/m的概率选择第m个对象。当该过程结束时,每一个对象具有相同的选中概率,即1/n。

    针对读取文本文件的例子,我们总选择第1行,并以概率1/2选择第2行,以1/3的概率选择第3行,
    依此类推,在这一过程结束时,每一行的选中概率是相等的,都是1/n,其中n是文件的总行数。

    给出伪代码:

    1
    2
    3
    4
    5
    i=0
    while more input lines
        with probaility 1/++i
          choice=this input line
    print choice

    这个问题可以抽象到更普遍的情况,就是蓄水池抽样问题。

     

    蓄水池抽样问题

    从n个元素中随机抽取k个元素,但n的个数无法事先确定。
    在实际应用中,往往会遇到很大数据流的情况。因此,我们无法先保存整个数据流然后再从中选取,而是期望有一种将数据流遍历一遍就得到所选取的元素,并且保证得到的元素是随机的算法。
    上面的问题就是k=1的的蓄水池抽样问题。

    看一下解决蓄水池抽样问题的算法:

    1.先选取n个元素中的前k个元素,保存在集合A中;

    2.即从第k+1个元素开始,
    每次先以k/(k+1)概率选择该元素,以k/(k+2)的概率选择第k+2个元素,
    以此类推,以k/m的概率选择第j个对象(k+1<=m<=n)。
    如果第m个元素被选中,则从A中随机选择一个元素并用元素m替换它;否则直接淘汰元素m;
    最终每个对象被选中的概率均为k/n。

    证明如下:

     

    蓄水池抽样算法的典型应用

    给定一个长度为N且没有重复元素的数组arr和一个整数M,实现函数等概率随机打印arr中的M个数。

    首先在0~n-1中随机得到一个位置a,打印arr[a],然后把arr[a]和数组最后位置的arr[n-1]交换;
    然后在0~n-2中随机得到一个位置b,然后把arr[b]和数组最后位置的arr[n-2]交换,

    arr:{0,1,2,3,...,b,...,n-2},n-1,

    依此类推,直到打印m个数即可。


    参考 《编程珠玑》
    Reservoir Sampling - 蓄水池抽样

  • 相关阅读:
    Javascript优化
    网页设计单页和多页的选择
    让404页面变得更加实用
    优秀的主页设计
    CSS常见布局解决方案
    前端极限性能优化
    记一次项目实训心得经验
    部署windows2008虚拟机
    httprunner学习总结
    意见汇总
  • 原文地址:https://www.cnblogs.com/binyue/p/3779186.html
Copyright © 2020-2023  润新知