首先通过一道题来理解什么是BitMap
题目:我有40亿个整数,再给一个新的整数,我需要判断新的整数是否在40亿个整数中,你会怎么做?
分析:假设一个int占用4个字节(32位),40个亿的话就是160亿个字节,大概相当于16GB,假设一台计算机只有2G内存,那么16G一次是加载不完的,要分8次加载,从磁盘加载数据是磁盘io操作,是非常慢的(比内存中的操作要慢百倍),每次加载这么大的数据,还要8次,那么查找的时间可以达到分钟甚至小时级了。
那是否可以把数据分散在8台计算机上,然后来一个新的数据,8台计算机同时找,然后再汇总出结果就行了?可以,这样做的话每台计算机都可以一次性把数据读入内存中,在查找比较时就不用来回加载数据了,省去了加载数据的开销,是个好办法。
哪还有什么其他可以实现的办法呢?
那就是BitMap
定义
位图BitMap:位图是一个数组的每一个数据的每一个二进制位表示一个数据,0表示数据不存在,1表示数据存在。
例如要存136这个数:
(1)首先确定这个数字在整个数据的那个区间,136/32=4,所以存放在第四个区间。
(2)确定这个数据在这个区间的第几位(bit),136%32=25,所在在第四区间的第25bit位上。
(3)将这个位置位置1,表示存在这个数。
另外由于BitMap的数据存储方式,因此还具有升序排序的性质。
具体实现
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
class Bitmap
{
public:
Bitmap(const int &size)
{
ve.resize((size>>5) + 1);//刚开始这里误用了reserve,编译一直提示超出访问范围,后来意识到reserve分配的内存不可用下标法直接访问
// //多开辟一个空间,原因是他只能表示区间[0,size)
}
void set_1(const int &num)//值1表示存在这个数
{
int index = num >> 5;//相当于num/32,位运算效率高于算数运算
int pos = num % 32;
ve[index] |= (1 << pos);
}
void set_0(const int &num)
{
int index = num >> 5;
int pos = num % 32;
ve[index] &= ~(1 << pos);
}
bool check(const int &num)//检查比较
{
int index = num >> 5;
int pos = num % 32;
bool mark = false;
if (ve[index] & (1 << pos))
mark = true;
return mark;
}
private:
vector<int > ve;
};
int main()
{ //测试
Bitmap bm(666666);
bm.set_1(222);
bm.set_1(3333);
bm.set_1(7777);
bm.set_1(9999);
bm.set_1(666666);
bm.set_0(1);
bm.set_0(666666);
cout << bm.check(1) << endl;
cout << bm.check(111) << endl;
cout << bm.check(222) << endl;
cout << bm.check(3333) << endl;
cout << bm.check(7777) << endl;
cout << bm.check(9999) << endl;
cout << bm.check(666666) << endl;
getchar();
getchar();
}