雕刻时光

just do it……nothing impossible
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

大数据量的时候查询某类数据

Posted on 2014-02-27 16:10  huhuuu  阅读(700)  评论(0编辑  收藏  举报

  有5亿个int范围的数字,量太大不能直接存放到内存下,如何处理可以找出中位数

  一般这种问题,可以考虑用分支的思想。

  1、由于不能直接放在内存里,先将这int范围的数字划分成2^16个区,第一个区的范围是[0 , (2^32-1) / (2^16)),以此类推。

  2、然后读入数据,分别将其累加到相应的分区。

  3、依次统计分区,读到累加数字个数大于等于2.5亿的时候,说明中位数在这个分区。

  4、重新读取所有数据,添加在这个分区范围的数据到数组中,对该数组排序就可以得到中位数了。

  

//有5亿个数字,量太大不能直接存放到内存下,如何处理可以找出中位数

#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;

int hash[128*128];
int shu[1000000];

int main(){
    int i,n=1<<32-1,m=128*128,temp;
    double second;

    for(i=0;i<m;i++){
        hash[i]=0;
    }

    for(i=0;i<i;i++){
        scanf("%d",&temp);
        second=m*temp/n;
        hash[(int)second]++;
    }

    int add=0 , end = n>>1;
    for(i=0;i<m;i++){
        add+=hash[i];
        if(add >= end){
            break;
        }
    }

    int left = (int) (n*1.0/m * (i-1));
    int right= (int) (n*1.0/m * i);
    int num=0;
    for(i=0;i<n;i++){
        scanf("%d",&temp);
        if(temp>=left && temp<=right){
            shu[add]=temp;
            add++;
        }
    }

    sort(&shu[0],&shu[add]);
    
    if(add%2 == 0)
        printf("%d\n",(shu[add/2-1]+shu[add/2])/2);
    else
        printf("%d\n",shu[add/2]);

    return 0;
}
View Code

  某网站每周都有很多浏览数据,每条PV日志都存一个1到2^63-1的数字表示浏览商品的ID。现在有10亿条PV日志文件,已知商品库中有5亿个不重复的商品,给你一台内存为2GB的电脑,让你找出哪些商品没有被浏览过。

  同样,考虑分支的思想。

  1、先将这long long 范围的数字划分成2^16个区,第一个区的范围是[0 , (2^32-1) / (2^16)),以此类推。

  2、将PV日志中的商品 与 商品库中的商品 分别放在硬盘下对应的2^16个文件中

  3、在第一个文件,排序PV日志中的商品 与 排序商品库中的商品,比较下,即可找出这个文件下那些商品未被浏览过。然后处理下一个文件。

 

   有5亿个商品成交数据,让你找出销量最高的10000个商品

   5亿商品的id如果不大,可以直接放在内存中的话,可以先建表统计相应的商品的个数,然后建一个大小为10000的小顶堆,更新即可。

   如果5亿商品的id比较大,不容易直接放到内存里,那就先分治,将数据按id范围分到N个硬盘的文件下,对单个文件里的商品排序统计,更新到小顶堆,在对其他文件依次处理。

 

总结:这类大数据的题目,一般用分支,在转化数据量足够小了可以在内存中处理了,在依次处理。