什么是bitmap
bit即比特,是计算机系统里边数据的最小单位,8个bit即为一个Byte。一个bit的值,要么是0,要么是1。bitmap可以理解为通过一个bit数组来存储特定数据的一种数据结构;
位图的概念:
所谓位图,就是用每一位来存放某种状态,适用于海量数据,数据无重复的场景,通常是用来判断某个数据存不存在的,缺点是不能计算出莫个数据出现了几次。
位图的优缺点
优点:节省空间,查找速度快
缺点:要求范围相对集中,范围特别分散的,空间消耗大;位图只对整型使用,浮点数、string等其他类型无法使用。
如果要判断其他类型,该类型如果可以使用哈希函数转为整型的。
应用场景
1、给40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何快速判断一个数是否在这40亿个数中?
解决方案:1、用int数组存储需要16G(40亿 * 4 byte 约 16G)内存
2、位图法只需要(pow(2,32) / 32 byte 约 512 Mb)
2、现在需要在一台只有4g内存的机器上对20亿个用户id进行去重,每个id占用4字节(正整数),你会怎么做?
3、有20个亿的用户,现在想要快速统计出有多少个用户是在登录状态,要怎么设计?
c++实现Bitmap
#include<iostream>
#include<vector>
using namespace std;
class BitMap {
public:
//构造器
//shift(5) 用于向右移动5位,因为int占用4字节,可以记录4*8个元素是否存在
BitMap(int num):n(num),mask(0x1F),shift(5),a(1+n/32,0){}
//将位图中的第i位设置为1,即把a[i/32]的第(i%32)位设置为1。
void set(int i) {
//i>>shift == i/32 ,i & mask == i % 32. |= 表示其中一个为 1 则为 1
// &= 表示两个都为 1 时才为 1 (a &= b 等同于 a = a & b)
a[i>>shift] |= (unsigned int)(1<<(i & mask)); //(1<<(i & mask))表示需要向右移动几 i & mask个bit位
// cout<<(unsigned int)(1<<(i & mask))<<" ";
}
int get(int i) {
return a[i>>shift] & (unsigned int)(1<<(i & mask));
}
//将位图中的第i位设置为 0
void clr(int i) {
a[i>>shift] &= ~(unsigned int)(1<<(i & mask));
}
private:
int n;
const int mask;
const int shift;
//数组
vector<unsigned int> a;
};
int main() {
BitMap bitmap(1000);
for(int i = 0 ; i < 100 ; i++){
bitmap.set(i);
}
bitmap.clr(11);
cout<<endl;
for(int i = 0 ; i < 100 ; i++){
bool res = bitmap.get(i);
cout<<res<<" ";
}
return 0;
}