Bootstrap

c++ 实现 Bitmap

什么是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;
}
;