海量数据处理一:一个实例

题目:

  给定一个输入文件,包含40亿个非负整数,请设计一种算法,产生一个不在该文件中的整数。假定你有1GB内存来完成这个任务。

一、几个数字

  1、40亿==4*109~~22*230==232,也就是说整数就这么多个

  2、1GB==230B==8*230b~~80亿,也就是说如果用一位表示一个整数,可以表示80亿个整数(虽然没有这么多)

二、需要用到的C++基础知识

  1、byte类型:byte并不是C++数据类型的关键字,如果希望使用byte类型,可以用unsigned char类型(8位)

  2、unsigned char 与 char的区别,char类型的首位代表的正负号,所以取值是-128~127。

  3、求类型的最大值 https://msdn.microsoft.com/en-us/library/296az74e(VS.80).aspx

1 #include<iostream>
2 using namespace std;
3 void main()
4 {
5     cout<<INT_MAX<<endl;
6     cout<<CHAR_MAX<<endl;
7     cout<<UCHAR_MAX<<endl;
8 }

  4、读文件操作

 1 #include<iostream>
 2 #include<fstream>
 3 using namespace std;
 4 void main()
 5 {
 6     ifstream infile;
 7     infile.open("data.txt");
 8     if(!infile){
 9         cerr<<"error:unable to open input file: "<<infile<<endl;
10         return;
11     }
12     char s[10];
13     while(!infile.eof())
14     {
15         infile.getline(s,‘\n‘);
16         cout<<s<<endl;
17     }
18 }

  5、位操作

    << :左移符号   ——  1<<2 ——> 00000001<<2 ——> 00000100(相应的>>)

    &:与操作,都为1取1,其余为0 01010101 & 00001111==00000101(相应的|和 ^)

    +:注意区分一下‘+‘和‘&‘,‘+‘ 是求和,逢2进1

三、位向量

  向量,vector,在Java里面就是一种大小可改变的数组

  位向量,首先是一个向量(数组),每个元素占用1位的内存空间,存放的是0和1。

四、问题解决

  1、思路:按照最开始的分析,如果用一位代表一个整数,那么1G内存完全可以放下

  (1)创建一二包含40亿个比特的位向量BV(采用的是byte严格来讲不叫位向量吧)

  (2)将BV的元素初始化为0

  (3)扫描文件中的所有数字,将代表当前数字的为置为1

  (4)从头遍历BV,返回第一个值为0的索引

  2、数据类型采用的是byte,byte类型占8位,因此可以代表8个整形数字,给定一个数,如何计算它的位置?

    byte []bv = new byte[num]

    0:在第一个元素的第8位

    7:在第一个元素的第1位

    10:10>7,所以第一个元素没有它的位置了,它在第二个元素的第三位

    ...

    对任一个整数n,它所在的位置为byte[n/8]的第1<<n%8位,大概是这样的赶脚:

    7 6 5 4 3 2 1 0 , 15 14 13 12 11 10 9 8,.....

    那给定一个位置,如上,求它代表的数字,即byte[i][1<<j](就先这样表示了)

    byte[0][1<<4] = i*8+4 = 4

    byte[1][1<<[1<<5]=1*8+5 = 13

  3、代码

 1 #include<iostream>
 2 #include<fstream>
 3 using namespace std;
 4 void main()
 5 {
 6     ifstream infile;
 7     infile.open("data.txt");
 8     if(!infile){
 9         cerr<<"error:unable to open input file: "<<infile<<endl;
10         return;
11     }
12     char s[10];
13     int temp=0;
14     unsigned int nInts = INT_MAX+1;
15     cout<<nInts<<endl;
16     unsigned char *bv = new unsigned char(nInts/8);
17     while(!infile.eof())
18     {
19         infile.getline(s,‘\n‘);
20         //cout<<typeid(s).name();
21         temp=atoi(s);
22         cout<<temp<<endl;
23         bv[temp/8] |= 1<<(temp%8);
24     }
25     for(int i=0;i<sizeof(bv);i++){
26         for(int j=0;j<8;j++){
27             if(((bv[i]>>j)&1) == 0){
28                 cout<<"result:"<<i*8+j<<endl;
29                 return;
30             }
31         }
32     }
33 }

  为了写出这段代码真是要了亲命了......

  我用古老的VC6.0运行的会报错误,但是结果还是算出来了,一定是VC的问题,嗯...

  但是我没有用海量的数据去测试

  这道题的思路和解法参考的是《面试金典》上的一道题,只不过我改成了C++版本,

  而且貌似它给的代码有些小bug,第18行的判断,未实验,感觉是....反正我的版本改了。

五、进阶:只能使用10MB内存

  遇到这种问题的时候,虽然我不保证能做出来,但是会这样去想:

  给了数据量和内存,先大概估算一下内存能否放的下:

  (1)可以放下,最简单的就是排序求解了

  (2)放不下,那就分而治之,划分为不同的子文件,分别求解

  但是现在好像可以这样想:

  (2)放不下,但是可以用位向量表示,位向量放的下,就可以用位向量求解

  (3)不能用位向量或者位向量也放不下,那就只能另寻他法了。

  对于这道题,我的第一反应也是划分子文件,再求解,但是看到了另一种差不多的方法...

  思路:

  显然现在这种情况(1)(2)都不行了,只能划分。

  10MB=10*220B~223B————221个整数

  所以划分为每块可以存储221个整数的区块

  区块的个数:232/221=211——2000块

  怎么个意思呢:

  稍微调节一下,区块大小220,块数212

  (1)首先扫描整个文件

    如果属于区间[0,220-1],区块1++;如果属于[220,221-1],区块2++...

  (2)各个区块,看各个区块的值是多少

    如果值<220,此区块一定少元素

  (3)在少数字的区块通过前述位向量的方法计算

  问题:

  因为存在重复数字,万一正好每个区间都不少呢?就只能对每一个区块都进行位向量计算吗?

  

  

  

时间: 2024-11-23 17:43:47

海量数据处理一:一个实例的相关文章

海量数据处理:经典实例分析

有关海量数据处理的问题,主要有以下3类:top K问题.重复问题.排序问题 top K 问题 例子有1亿个浮点数找出其中最大的10000个 解决方案 将数据全部排序 局部淘汰法 分治法 Hash法 最小堆 不同应用场景的解决方案 单机单核足够大内存 单机多核足够大内存 单机单核受限内存 多机受限内存 小结 重复问题 排序问题 数据库排序法 分治法 位图法 top K 问题 在大规模数据处理中,经常会遇到的一类问题:在海量数据中找出出现频率最高的前K个数,或者从海量数据中找出最大的前K个数,这类问

海量数据处理算法总结【超详解】

1. Bloom Filter [Bloom Filter]Bloom Filter(BF)是一种空间效率很高的随机数据结构,它利用位数组很简洁地表示一个集合,并能判断一个元素是否属于这个集合.它是一个判断元素是否存在集合的快速的概率算法.Bloom Filter有可能会出现错误判断,但不会漏掉判断.也就是Bloom Filter判断元素不再集合,那肯定不在.如果判断元素存在集合中,有一定的概率判断错误.因此,Bloom Filter不适合那些“零错误”的应用场合. 而在能容忍低错误率的应用场合

海量数据处理算法

1. Bloom Filter [Bloom Filter]Bloom Filter(BF)是一种空间效率很高的随机数据结构,它利用位数组很简洁地表示一个集合,并能判断一个元素是否属于这个集合.它是一个判断元素是否存在集合的快速的概率算法.Bloom Filter有可能会出现错误判断,但不会漏掉判断.也就是Bloom Filter判断元素不再集合,那肯定不在.如果判断元素存在集合中,有一定的概率判断错误.因此,Bloom Filter不适合那些"零错误"的应用场合. 而在能容忍低错误率

海量数据处理 算法总结

前面我们说海量数据处理提到,从算法的角度去考虑处理海量数据. 1. Bloom Filter [Bloom Filter]Bloom Filter(BF)是一种空间效率很高的随机数据结构,它利用位数组很简洁地表示一个集合,并能判断一个元素是否属于这个集合.它是一个判断元素是否存在集合的快速的概率算法.Bloom Filter有可能会出现错误判断,但不会漏掉判断.也就是Bloom Filter判断元素不再集合,那肯定不在.如果判断元素存在集合中,有一定的概率判断错误.因此,Bloom Filter

海量数据处理--hash和bit-map

问题实例: 海量日志数据,提取出某日访问百度次数最多的那个IP. 答:对于ip,最多也就2^32个.所以可以很好地通过hash函数映射到内存中,再进行统计. IP最多为2^32个,为4G,一次放入内存中不行,可以采用分而治之的方法,先Hash(IP)/1024,将IP地址分别映射到1024个小文件中,每个文件4M,再将每个小文件中的IP放入内存中,进行hashmap,统计出出现频率最高的那个IP,最后可以得到1024个出现高频的IP,采用冒泡排序,可以迅速找出频率最高的那个IP.1 原理简述:

【转】海量数据处理算法-Bloom Filter

1. Bloom-Filter算法简介 Bloom Filter(BF)是一种空间效率很高的随机数据结构,它利用位数组很简洁地表示一个集合,并能判断一个元素是否属于这个集合.它是一个判断元素是否存在于集合的快速的概率算法.Bloom Filter有可能会出现错误判断,但不会漏掉判断.也就是Bloom Filter判断元素不再集合,那肯定不在.如果判断元素存在集合中,有一定的概率判断错误.因此,Bloom Filter不适合那些“零错误”的应用场合.而在能容忍低错误率的应用场合下,Bloom Fi

海量数据处理方法

1.hashing 适用范围:快速查找,删除的基本数据结构,通常需要总数据量可以放入内存.  这里的hashing和 hashmap是不一样的概念,这里的hash指的是hashtable,可以看例子:(比较两个字符串的包含问题) 问题实例: 1).海量日志数据,提取出某日访问百度次数最多的那个IP. IP的数目还是有限的,最多2^32个,所以可以考虑使用hash将ip直接存入内存,然后进行统计. 2.bitmap 适用范围:可进行数据的快速查找,判重,删除,一般来说数据范围是int的10倍以下.

被神化的海量数据处理和高并发处理

http://blog.csdn.net/hawksoft/article/details/7192207 实任何简单的问题,只要规模大了都会成为一个问题,就如中国人口多,很多小问题都会变成大问题一样.但处理这种海量数据的方法无非就是分治和”人海”战术.使用人海战术的前提是问题的划分能够支持这种人海战术,其手段无非是切割(纵向,横向)和负载均衡.纵向分隔主要是按业务(功能)来分,也就是所谓面向服务架构,横向分隔方式比较多,主要依赖于所处理的对象属性,比如时间属性或者特定业务数据属性划分(比如铁路

关于海量数据处理的相关问题

看过很多面经,里面都会问到海量数据处理的问题.虽然在学校根本遇不到这样的情境,但很多方法还是需要我们去好好了解一下的,也是为了以后的工作做准备吧. 搜集了一些有关海量数据处理的问题和解答,如下: 1.海量日志数据,提取出某日访问百度次数最多的那个IP. 此题,在我之前的一篇文章算法里头有所提到,当时给出的方案是:IP的数目还是有限的,最多2^32个,所以可以考虑使用hash将ip直接存入内存,然后进行统计. 再详细介绍下此方案:首先是这一天,并且是访问百度的日志中的IP取出来,逐个写入到一个大文

转 十道海量数据处理面试题与十个方法大总结

作者:July.youwang.yanxionglu. 时间:二零一一年三月二十六日本文之总结:教你如何迅速秒杀掉:99%的海量数据处理面试题.有任何问题,欢迎随时交流.指正.出处:http://blog.csdn.net/v_JULY_v. 第一部分.十道海量数据处理面试题 1.海量日志数据,提取出某日访问百度次数最多的那个IP. 首先是这一天,并且是访问百度的日志中的IP取出来,逐个写入到一个大文件中.注意到IP是32位的,最多有个2^32个IP.同样可以采用映射的方法,比如模1000,把整