大数据算法-空间时间亚线性算法举例-水库抽样问题

本文介绍了一种在数据流中进行均匀随机抽样的方法——水库抽样算法。该算法适用于未知大小的数据集,只需扫描数据一次,即可实现O(k)的时间复杂度。文章详细解释了算法的工作原理,包括如何在接收新元素时以k/i的概率更新样本,并提供了C++实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

从N个元素中随机抽取k个数,其中N无法确定

在数据流的情况下,每个数据有且仅有被读取一次,而且数据流很大,保存的量相比抽取的量会小得多

应用场景

输入:一组数据,其大小未知

输出:这组数据的k个均匀抽样(在非常多的数据里面每个数据被抽到的概率都是一致的)

要求:

        仅仅只能扫描数据一次

        时间复杂度为0(k)

        扫描到数据的前n个数字时(n>k),保存当前已扫描数据的k个抽样

水库抽样算法

1.申请一个长度为k的数组A保存抽样

2.保存首先接受到的k个元素

3,当接受到第i个新元素t时,以k/i的概率随机替换A中的元素(及生成[1,i]间随机数j,若j<=k,则以t替换A[j])

 

性质一:该采样是均匀的

      k/i*(1--1/i+1)*(1--1/i+2)*............*(1--1/n)=k/n

   当接受到第i个数的时候,那么第i个数被替换的概率为k/i。

 当接受到第i+1个数的时候,第i+1个数字被替换 的概率为k/i+1,数组中每个数字被替换的概率是一样的都是1*k,两者相乘,所以第i个数被替换的概率为1/i+1 ,即第i个数不被替换的概率为(1--1/i+1)

所以可以得出到接受n个数时,第i个数更改的概率为k/i  以此类推i+1个数更改

#include <iostream>
#include <cstdlib>
#include <ctime>

using namespace std;
int random(int min ,int max)
{

    return (min+(rand()%(max-min+1)));
}

int main()
{

    srand(unsigned(time(0)));
    int k;
    int i;
    cout << "Input k:" ;
    cin >> k;
    double *ans = new double[k+1];
    double input;
    cout << "Input k numbers:" << endl;
    for(i = 1;i <= k; ++i)
    {
        cin >> ans[i];
    }
    cout << "Input stream numbers:(q to quit)" << endl;

while(true)
    {

        int j = random(1,i);
        if(!(cin >> input)) break;
        if(j <= k)
            ans[j] = input;
        //output
        cout << "Ans :" ;
        for(int p = 1;p < k; ++p)
            cout << ans[p] << ",";
        cout << ans[k] << endl;
        i++;
    }

    delete [] ans;
    return 0;
}
 

  

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值