主要参考了以下两篇文章
[《编程珠玑》学习总结1—bitmap]
[浅谈bitmap算法]
基本概念
- 什么是bitmap
我自己的理解是:首先是一种map,其次映射到bit位。关键还是它是一种映射,映射到的value由于是bit,比较节省空间。bitmap是一种映射,每一个bit位用来表示key所对应的value是否存在。 - 优点和缺点是什么
优点:节省空间,并且,位运算比较快
缺点:不能处理重复元素。
思路
bitmap的思路是Hash,所以,需要解决的问题是,如何把一个整数映射到bitmap当中。比如,int a = 0; 它有32位bit,先假设int a = 0; 栈2个字节,那么16位,可以表示16个数字是否存在,从0开始。0000 0000 0000 0000,由于有16位,所以可以用来表示16个数字。比如,
0000 0000 0000 0001 -> 0 表明0是存在的
0000 0000 0000 0010 -> 1 表明1是存在的
…
1010 0001 0101 0011 -> 表明,0 , 1, 4 ,6 8, 13, 15都是存在的。关键就是对于一个val,如何将它映射为一个bitmap。不放这么考虑,对于 int a[2];
a[0]: 0000 0000 0000 0000 0000 0000 0000 0000 (0 - 31)
a[1]: 0000 0000 0000 0000 0000 0000 0000 0000 (32 - 63)
这其实相当于二维表,当然在内存中a[0]是byte进行排列的,但是我现在可以忽略这一点。比如,对于32,如何计算它的存储位置?
row = val / 32;
col = val % 32;
对于32而言,row = 1 = 32/32; 所以,存在a[1]里面,col = 0 = 32%32;相当于是如下的存储:
a[0]: 0000 0000 0000 0000 0000 0000 0000 0000 (0 - 31)
a[1]: 0000 0000 0000 0000 0000 0000 0000 000 1 (32 - 63)
所以row_index = val / 32;col_index = val%32, 那么问题来了,a[row_index]这点你是可以做到得,但是由于它已经是变量(最小的操作单位),没有办法对一个变量内部进行寻址。位元素在此处就要派上用途了!对变量内部的col_index进行置位。
具体来说,以32为例,col_index = 0.相当于偏移量为0,需要在偏移量为0的地方进行置位。可以用如下操作 1 << col_index ,将1左移动col_index位,然后再和a[0]进行或操作,那么就完成了对变量内部col_index的置位。
a[row_index] = a[row_index] | ( 1 << col_index ) ,这个就是置位的公式。
a[row_index] = a[row_index] & ~( 1 << col_index ) ,这个是清除操作
return a[row_index] & ( 1 << col_index ), 这个是获取当前位的操作。
代码
#include <cstdio>
#define BITPERWORD 32
#define SHIFT 5
#define MASK 0x1F
#define N 32
int a[ N/BITPERWORD]; // [0, N