1.概述
本文将讲述Bit Map算法的相关原理,以及一些利用场景,例如BitMap解决海量数据寻找重复、判断个别元素是否在海量数据当中等问题。
最后说说BitMap的特点以及在各个场景的使用特性。
2.算法
题目:32位整数中有40亿个不重复的整数,给定一个整数,确定是否在40亿个中出现。PC内存为2G
思考:40亿个int大约占 (40*10^9*4)/1024/1024/1024 约为14.9G,很明显内存一般放不下。
因此不可能将这40亿数据放在内存中计算。但是想要快速的实现,就应该讲数据放在内存中,所以
问题就变为如何在2G内存空间以内存储着40亿个整数。一个int数在32位系统中中是占4个字节,即需要32bit
如果能够用一个bit位来表示一个int整数,那么存储空间将会减少32倍,大概为500M,这样的话我们完全可以将这
40亿个int数放在内存中进行处理。
具体实现思路:
1个int占4个字节即4*8=32位,那么我们需要申请一个int数组长度为 int tmp[1+N/32]即可存储完这些数据,
其中N代表要进行查找的总数,tmp中的每一个元素在内存都占32位,可以对应表示十进制数0~31,所以
可得到BitMap表:
tmp[0]:可表示0~31
tmp[1]:可表示32~63
tmp[2]:可表示64~95
...
那么接下来就看看十进制数如何转换为对应的bit位:
假设这40亿int数据为:6 3 8 32 36 ... 那么具体的BitMap表示为:
如何判断int数字在tmp数组的哪个下标,这个其实可以通过直接除以32取整数部分,例如:
整数8除以32 取整 等于0,那么8就在tmp[0]上。另外,我们如何知道8在tmp[0]中32个位中的哪个位呢,
这种情况直接mod32即可,比如整数8,在tmp[0]中的第 8mod32 = 8位。
3.bitmap算法原始实现
<span style="font-size:14px;">//set 设置所在的bit位为1
void set(int i) {
a[i>>SHIFT] |= (1<<(i & MASK));
}
//clr 初始化指定的bit位为0
void clr(int i) {
a[i>>SHIFT] &= ~(1<<(i & MASK));
}
//test 测试所在的bit为是否为1
int test(int i){
return a[i>>SHIFT] & (1<<(i & MASK));
}
int main()
{ int i;
for (i = 0; i < N; i++)
clr(i);
while (scanf("%d", &i) != EOF)
set(i);
for (i = 0; i < N; i++)
if (test(i))
printf("%d\n", i);
return 0;
}</span>
代码解析:
void
set(
int