数据结构与算法(8) - bitmap

0. 何为bitmap

说白了就是一个数组,但是这个数组的定义和使用方式有些区别。他的每一个元素是一个bit。

1. 具体场景

构建一个数字集合,数字范围是1 - 1024,如何快速判断一个数是否在这个集合中。
场景很简单,构建一个int型的数组arr就可以了,下标表示对应的数字,如果 a[ 1 ] = 0 表示数字1不存在,a[1] != 0 ,表示数字1存在。

2. 上边的方式占用多大空间?

一共1024个元素,每个元素都是int类型,那么一共需要开辟N = sizeof(int) * 1024 个字节,也就是N= 4096个字节

3. 改进

上边的int类型数组,其实每一个元素只标定两种情况 0非 0,那用bool类型的数组就更合适一些啊。没错,如果换成bool数组,也是可以的,需要的空间大小是N / 4字节,也就是1024字节。

4. 再次改进

一个bool型虽然在使用时只表示两种逻辑,即truefalse,但是实际上底层用了8个bit。最最基础的,表达truefalse的应该是一个二进制位,也就是一个bit

构建一个bit数组,实际上就是构建bitmap了。

如果用bitmap来实现上边情况的话,需要的空间大小是N / 4 / 8 = 128 字节 。如此可见空间有所节约。

5. c++实现bitmap

c++ code:

#include <iostream>
#include <cstring>

using namespace std;

class bitmap{
public:
    bitmap(int _ss){
        ss = _ss;  // 要存的总数
        int_ss = ss / 32 + 1;
        ptr = new unsigned int[int_ss];    
        memset(ptr, 0, sizeof(ptr));
    }

    ~bitmap(){
        delete[] ptr;
    }

    void insert(int x){
        int idx = x / 32;
        int bit_idx = x % 32;
        ptr[idx] |= ( 1 << (31 - bit_idx) );
    }

    void erase(int x){
        int idx = x / 32;
        int bit_idx = x % 32;
        ptr[idx] &= ~( 1 << (31 - bit_idx) );
    }

    bool query(int x){
        int idx = x / 32;
        int bit_idx = x % 32;
        if( ( ptr[idx] & ( 1 << (31 - bit_idx) ) ) == 0) return false;
        return true;
    }

    // 打印当前bitmap情况
    void print(){
        for(int i = 0; i < int_ss; ++i){
            printBin(ptr[i]);
        }
    }

private:
    int ss = 0;  // 要存储的最大整数
    int int_ss = 0;
    unsigned int *ptr = nullptr;

    void printBin(int x){
        for(int i = 0; i < 32; ++i){
            printf("%d",  (x >> (31 - i)) & 1 );
            if((i + 1) % 8 == 0) printf(" ");
        }
        cout << endl;
    }
};

int main(){
	
	// test code
    bitmap a(31);

    while(1){
        int op, x;
        cin >> op >> x;
        a.print();
        if(op == 1) {
            a.insert(x);
            a.print();
        }else if(op == 0){
            a.erase(x);
            a.print();
        }else {
            cout << a.query(x) << endl;
        }
        
    }
    

    



    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值