位图法-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 <iostream>
#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

posted @ 2011-08-14 10:39  xiaodongrush  阅读(1958)  评论(0编辑  收藏  举报