位图法-bitmap
1. 简述
昨天在看海量数据处理的题目,其中有一道题用的就是2-bitmap,今天学习一下bitmap,主要参考资料就是百度百科。
2. 定义
bitmap是通过1个位表示一个状态,比如:int类型有2^32个数字,即4G个数字,那么每个数字一个状态,就是2^32个bit,即512 MB。
3. 应用
· 给40亿个不重复的unsigned int的整数,没排过序的,然后再给一个数,如何快速判断这个数是否在那40亿个数当中
首先,将这40亿个数字存储到bitmap中,然后对于给出的数,判断是否在bitmap中即可。
· 使用位图法判断整形数组是否存在重复
遍历数组,一个一个放入bitmap,并且检查其是否在bitmap中出现过,如果没出现放入,否则即为重复的元素。
· 使用位图法进行整形数组排序
首先遍历数组,得到数组的最大最小值,然后根据这个最大最小值来缩小bitmap的范围。这里需要注意对于int的负数,都要转化为unsigned int来处理,而且取位的时候,数字要减去最小值。
· 在2.5亿个整数中找出不重复的整数,注,内存不足以容纳这2.5亿个整数
参考的一个方法是:采用2-Bitmap(每个数分配2bit,00表示不存在,01表示出现一次,10表示多次,11无意义)。其实,这里可以使用两个普通的Bitmap,即第一个Bitmap存储的是整数是否出现,如果再次出现,则在第二个Bitmap中设置即可。这样的话,就可以使用简单的1-Bitmap了。
4. 实现
#include <cmath>
using namespace std;
#define MAX 536870912 // pow(2,29)
unsigned char bitmap[(unsigned int)MAX];
void init() {
memset(bitmap, 0, MAX*sizeof(unsigned char));
}
void set(unsigned int num) {
bitmap[num/8] |= (128 >> num%8); // pow(2,7)=128
}
bool find(unsigned int num) {
return bitmap[num/8] & (128 >> num%8);
}
int main() {
init();
for(int i=-10; i<10; i++)
set(i);
for(int i=-20; i<20; i++)
if(find(i))
cout << "i: " << i << endl;
system("PAUSE");
return 0;
}
对于实现来说,百科上面的代码用的是int数组,不过char数组应该也是一样的,就是相当于数组长度大了点,差不多。对于unsigned int,主要是在除法和取余运算上的问题,因此要保证set和find函数中使用的一定是unsinged int类型,即要被强制转化的参数。
5. 备注
普通bitmap的局限就是要求所有的状态都要放在内存里面,假设状态数量是2^64的话,那么内存肯定放不下,或者状态数量不变为2^32,但是内存要求10MB的话,就没法办了。另外好像有bitmap+mapreduce的方法,这个以后有机会再研究。
6. 参考
十道海量数据处理面试题与十个方法大总结 http://blog.csdn.net/v_JULY_v/article/details/6279498
位图法_百度百科 http://baike.baidu.com/view/6102616.html?tp=5_11