bitmap与2bitmap实现

来源:互联网 发布:流行聊天软件 编辑:程序博客网 时间:2024/05/17 03:51

Bitmap就是用一个bit位来标记某个元素是否存在,而2Bitmap就是用两个bit为来标记某个元素的个数,00,01,10,11(分别表示0,1,2,3,0表示不存在,1表示存在1次,后面依次)。

Bitmap能用来处理下面的两个问题:

(1)、在2.5亿个整数找出不重复的整数,内存不足以容纳着2.5亿个整数

(2)、腾讯面试题:给40亿个不重复的unsigned int的整数,没排过序的,然后再给一个数,如何快速判断这个数是否在那40亿个数当中?

对于问题1,整数可能是正数也可能是负数,首先只考虑正整数情况,采用2Bitmap方法,用00表示不存在,01表示出现1次,10表示出现2次及以上,此方法总共需要的内存2^31*2bit = 1Gb = 128MB(32位的正整数有2^31个,每个存储需要2bit,所以就是1Gb,换成字节就是128MB),这样内存就应该能够容纳了,最后在处理完所有的数后,只要输出对应位为01的数即可。如果这2.5亿个数里面既有正数又有负数那么就用两个2Bitmap分别存储正数和负数(取绝对值存储),零就随便放,这是所需要的内存是512MB。

对于问题2,直接用Bitmap即可,0表示存在,1表示不存在。


Bitmap实现:

参考:http://blog.csdn.net/QIBAOYUAN/article/details/5914662

[cpp] view plaincopyprint?
  1. #include <cstdio>  
  2. #include <iostream>  
  3. using namespace std;  
  4. #define WORD 32  
  5. #define SHIFT 5 ////移动5个位,左移则相当于乘以32,右移相当于除以32取整  
  6. #define MASK 0x1F //16进制下的31  
  7. #define N 1024*1024*1024  
  8. int bitmap[1 + N / WORD];  
  9. /* 
  10.  * 置位函数——用"|"操作符,i&MASK相当于mod操作 
  11.  * m mod n 运算,当n = 2的X次幂的时候,m mod n = m&(n-1) 
  12.  */  
  13. void set(int i) {  
  14.     bitmap[i >> SHIFT] |= (1 << (i & MASK));  
  15. }  
  16. /* 清除位操作,用&~操作符 */  
  17. void clear(int i) {  
  18.     bitmap[i >> SHIFT] &= ~(1 << (i & MASK));  
  19. }  
  20. /* 测试位操作用&操作符 */  
  21. int test(int i) {  
  22.     return bitmap[i >> SHIFT] & (1 << (i & MASK));  
  23. }  
这里由于int型为32个bit,那么每个bitmap[i]就能保存32个相邻整数是否存在的信息,而为了区分就用余数来表示其位置,例如对于号码 89256,由于89256 mod 32=2789…8,这样我们应该置a[2789]中32位字符串的第8位(从低位数起)为1。

2Bitmap实现:

[cpp] view plaincopyprint?
  1. #include <cstdio>  
  2. #include <iostream>  
  3. using namespace std;  
  4.   
  5. unsigned char bitmap[1005];  
  6.   
  7. //x表示一个整数,num表示bitmap中已经拥有x的个数  
  8. //由于我们只能用2个bit来存储x的个数,所以num的个数最多为3  
  9. void set(int x,int num){  
  10.     int m = x >> 2;  
  11.     int n = x & 3;  
  12.   
  13.     //将x对于为值上的个数值先清零,但是有要保证其他位置上的数不变  
  14.     bitmap[m] &= ~((0x3<<(2*n)) & 0xFF);  
  15.     //重新对x的个数赋值  
  16.     bitmap[m] |= ((num&3)<<(2*n) & 0xFF);  
  17. }  
  18.   
  19. void clear(int x){  
  20.     int m = x >> 2;  
  21.     int n = x & 3;  
  22.     bitmap[m] &= ~((0x3<<(2*n)) & 0xFF);  
  23. }  
  24.   
  25. unsigned char get(int x){  
  26.     int m = x >> 2;  
  27.     int n = x & 3;  
  28.   
  29.     return (bitmap[m] & (0x3<<(2*n))) >> (2*n);  
  30. }  
  31.   
  32. void add(int x){  
  33.     int num = get(x);  
  34.     set(x,num+1);  
  35. }  
上面的&0xFF其实没用,作用就是为了“确保”,unsigned char为8个bit位。

总结:Bitmap是简单快速的数据结构,长用于空间的优化。

0 0