Bitmap 海量数据处理
来源:互联网 发布:pdf sql pan 编辑:程序博客网 时间:2024/05/29 08:50
Bitmap:
说明:采用一个bit来标记某个value,可以大大节省存储空间。
优点是占用内存少,比如N为一亿(10000 0000),只需要N/8=1250 0000个byte,约等于12Mb。缺点为不能重复数据进行排序和查找
思想:利用一个byte中的8个bit来表示8个数。某数出现,利用映射将对应bit位置1。
比如元素3,在8bit的映射为
再来个元素5,在8bit的映射为
映射表为:
A[0]->0~7;
A[1]->8~15;
A[2]->16~23;
…….
具体实现:(例子为32位)
#include <stdio.h>#define BITSPERWORD 32#define SHIFT 5#define MASK 0x1F//#define N 10000000#define N 100 int a[1 + N/BITSPERWORD];//申请内存的大小 void set(int i) {// a[i>>SHIFT] |= (1<<(i& MASK)); a[i/BITSPERWORD] |= (0x01<<(i%BITSPERWORD));}//clr 初始化所有的bit位为0void clr(int i) {// a[i>>SHIFT] &= ~(1<<(i & MASK)); a[i/BITSPERWORD] &= ~(0x01<<(i%BITSPERWORD));}//test 测试所在的bit为是否为1int test(int i){ return a[i>>SHIFT] & (0x01<<(i & MASK));} int main(){ int i; for (i = 0; i < N; i++) clr(i); for(i=0;i<N;i+=4) set(i); for (i = 0; i < N; i++) if (test(i)) printf("%d ", i); return 0;}
a[i/BITSPERWORD]或a[i>>SHIFT],实现i/32,即求出操作bit所在数的下标。
0x01<<(i%BITSPERWORD)或(1<<(i& MASK)),取得该操作bit的具体位置。
实例:
1、 已知某个文件内包含一些电话号码,每个号码为8位数字,统计不同号码的个数。
思路:8位数,0000 0000~9999 9999,范围为一亿。需要10^8个bit,12M左右字节。
实现:
int const nArraySize = 100000000 /(sizeof(int)*8) + 1;int Bitmap[nArraySize];void MapPhoneNumberToBit(int nNumber){ Bitmap[nNumber/ (8*sizeof(int))] |= 0x00000001<<(nNumber%(8*sizeof(int)));}
2、2.5亿个整数中找出不重复的整数的个数,内存空间不足以容纳这2.5亿个整数。
思路:用两个bit来表示一个数。0表示整数未出现,1表示出现一次,2表示出现多次。在遍历这些数的时候,如果对应位置的值是0,则将其置为1;如果是1,将其置为2;如果是2,则保持不变。注意控制与置位的分离。
实现
#include<memory.h> unsigned char flags[1000]; //数组大小自定义 unsigned get_val(int idx) { // | 8 bit | // |00 00 00 00| //映射3 2 1 0 // |00 00 00 00| //表示7 6 5 4 // …… // |00 00 00 00| int i = idx/4; //一个char 表示4个数, int j = idx%4; unsigned ret = (flags[i]&(0x3<<(2*j)))>>(2*j); //0x3是0011 j的范围为0-3,因此0x3<<(2*j)范围为00000011到11000000 如idx=7 i=1 ,j=3 那么flags[1]&11000000, 得到的是|00 00 00 00| //表示7 6 5 4 return ret; } unsigned set_val(int idx, unsigned int val) { int i = idx/4; int j = idx%4; unsigned tmp = (flags[i]&~((0x3<<(2*j))&0xff)) | (((val%4)<<(2*j))&0xff); flags[i] = tmp; return 0; } unsigned add_one(int idx) { if (get_val(idx)>=2) { //这一位置上已经出现过了?? return 1; } else { set_val(idx, get_val(idx)+1); return 0; } } //只测试非负数的情况; //假如考虑负数的话,需增加一个2-Bitmap数组. int a[]={1, 3, 5, 7, 9, 1, 3, 5, 7, 1, 3, 5,1, 3, 1,10,2,4,6,8,0}; int main() { int i; memset(flags, 0, sizeof(flags)); printf("原数组为:"); for(i=0;i < sizeof(a)/sizeof(int); ++i) { printf("%d ", a[i]); add_one(a[i]); } printf("\r\n"); printf("只出现过一次的数:"); for(i=0;i < 100; ++i) { if(get_val(i) == 1) printf("%d ", i); } printf("\r\n"); return 0; }
3、给你一个文件,里面包含40亿个整数,写一个算法找出该文件中不包含的一个整数, 假设你有1GB内存可用。如果你只有10MB的内存呢?
思路:40亿个整数(40*10^8*4byte~16GB)。
A、 内存为1G
显然无法将16G的数据直接放入1G内存,采用bitmap算法,40*10^8bit= 0.5G(大约),满足1G的内存。
B、 内存为10M
如果我们只有10MB的内存,明显使用BitMap也无济于事了。 内存这么小,注定只能分块处理。比如分块的大小是1000,那么第1块的范围就是0到999,第2块的范围就是1000 到1999……
实际上并不保存这些数,而是给每一个块设置一个计数器。 这样每读入一个数,就在它所在的块对应的计数器加1。处理结束之后,我们找到一个块,它的计数器值小于块大小(1000),说明了这一段里面一定有数字是文件中所不包含的。然后我们单独处理这个块即可。
参考:
http://blog.csdn.net/hguisu/article/details/7880288
http://hawstein.com/posts/12.3.html
http://blog.csdn.net/chris820313/article/details/6795561
- 海量数据处理之Bitmap
- 海量数据处理之Bitmap
- 海量数据处理-----bitmap
- Bitmap 海量数据处理
- 海量数据处理之bitmap实现
- 海量数据处理---位图法Bitmap
- 海量数据处理--位图(BitMap)
- JAVA海量数据处理之二(BitMap)
- bitmap 在海量数据处理中的使用
- 海量数据处理——位图法bitmap
- 海量数据处理——位图法bitmap
- 海量数据处理(1)Bitmap, Bloom Filter, Hash(转)
- 海量数据处理系列----C++中Bitmap算法的实现
- 海量数据处理系列----C++中Bitmap算法的实现
- 海量数据处理系列----C++中Bitmap算法的实现
- 海量数据处理系列----C++中Bitmap算法的实现
- [算法系列之十八]海量数据处理之BitMap
- 海量数据处理系列之:用C++实现Bitmap算法
- 读书札记-2013年12月
- 团伙-并查集
- DSP6000的几个简单优化技巧
- 数字信号处理的学习资源
- Android 保存数据的四种方法
- Bitmap 海量数据处理
- 白话压缩感知(含Matlab代码)
- js模拟支付宝提交表单
- 当eclipse工程出现红色感叹号的解决方法
- windows下远程访问ubuntu
- OpenCV基础篇之绘图及RNG随机数对象
- OpenCV基础篇——图形图像旋转
- switch内部的变量定义
- JVM性能优化:垃圾收集