BitMap的C++实现

BitMap算法的实现

所谓的Bit-map就是用一个bit位来标记某个元素对应的Value, 而Key即是该元素。由于采用了Bit为单位来存储数据,因此在存储空间方面,可以大大节省。

我们知道,一般可以直接操控的最小的单位是字节,比如在C/C++中,定义一个类型char,对它进行各种操作。然后很多时候,面对一个很大数据量,且我们仅仅希望知道某个数是否存在,我们不妨可以(有时候是必须)使用Bitmap算法来完成相关操作。比如腾讯的下面这道题:

在40亿个没有排序的无符号整数中,我们如何快速判断某个无符号整数是否在这40亿个数中?

40亿,这是一个很大的数字,就是海量数据的处理,所以我们必须要考虑到内存的问题。我们知道一个无符号整数的大小为4个字节,那么40亿个需要占多少的内存?4*40亿是多大量级?咋一看有点难算,不过我们可以估算一下。
1KB=1024B
1MB=1024KB
1GB=1024MB
我们近似估计一下,1GB≈1000 * 1000 * 1000B= 1 000 000 000B = 10亿B,因此40亿*4B / 10亿B = 16G。就是说需要占据大概16GB的内存,这显然对于一般的电脑是不行的。

如果我们可以使用位图来存,一整型占4字节32比特位,因此如果用一个bit来存的话,在上面的例子中仅仅需要16G/32=0.5G大概就是500MB的内存。

题目要求我们快速判断,最快的算法当然是O(1)的操作,我们可以开一个无符号整型最大值的空间(保证这42亿个数都在这个范围内),每个数映射一个bit位,如果存在就将该bit位置1,不然就置0。因此想要查找某个数只需要开他映射的那个比特位是0还是1就可以了。

比如我们想要在这些数中查找一个33。

首先我们要开辟一块size_t(无符号整型)的空间,我们不妨使用vector v 来存。
其中每个元素都是size_t占4个字节32位,如下图(每个空格代表一个bit位)

这里写图片描述

刚开始每个空格全是0,这时候我们存一个33,v[0]对应着0-31的比特位,v[1]对应着32-63的比特位,因此33就在v[1]第二个比特位。。。我们只需要将这个比特位置1就好了,到时候查找也是这个位是否为1。

bitmap表为:

v[0] ——> 0 - 31

v[1] ——> 32 - 63

v[2] ——> 64 - 95

v[3] ——> 96 - 127

……

结论:对于任意一个数x,x / 32对应着它在vector的第几个位置,x % 32对应它的比特位。

下面给出C++代码的实现。

class BitMap
{
public:
    BitMap(size_t num)
    {
        _v.resize((num >> 5) + 1); // 相当于num/32 + 1
    }

    void Set(size_t num) //set 1
    {
        size_t index = num >> 5; // 相当于num/32
        size_t pos = num % 32;
        _v[index] |= (1 << pos);
    }

    void ReSet(size_t num) //set 0
    {
        size_t index = num >> 5; // 相当于num/32
        size_t pos = num % 32;
        _v[index] &= ~(1 << pos);
    }

    bool HasExisted(size_t num)//check whether it exists
    {
        size_t index = num >> 5;
        size_t pos = num % 32;
        bool flag = false;
        if (_v[index] & (1 << pos))
            flag = true;
        return flag;

    }

private:
    vector<size_t> _v;
}; 

完整代码见github之BitMap

这是一个用于C++ MFC开发的Bitmap图片操作类,在文件中叫CBitmapEx,可用于放大,缩小,翻转,过渡和其他有用的功能,有兴趣的朋友可以下载看看。 部分public method: // // void Create(long width, long height); // void Create(CBitmapEx& bitmapEx); // void Load(LPTSTR lpszBitmapFile); // void Save(LPTSTR lpszBitmapFile); // void Scale(long horizontalPercent=100, long verticalPercent=100); // void Rotate(long degrees=0, _PIXEL bgColor=_RGB(0,0,0)); // void FlipHorizontal(); // void FlipVertical(); // void MirrorLeft(); // void MirrorRight(); // void MirrorTop(); // void MirrorBottom(); // void Clear(_PIXEL clearColor=_RGB(0,0,0)); // void Negative(); // void Grayscale(); // void Sepia(long depth=34); // void Emboss(); // void Engrave(); // void Pixelize(long size=4); // void Draw(HDC hDC); // void Draw(long dstX, long dstY, long width, long height, // CBitmapEx& bitmapEx, long srcX, long srcY); // void Draw(long dstX, long dstY, long width, long height, // CBitmapEx& bitmapEx, long srcX, long srcY, long alpha); // void Draw(long dstX, long dstY, long dstWidth, long dstHeight, // CBitmapEx& bitmapEx, long srcX, long srcY, long srcWidth, long srcHeight); // void Draw(long dstX, long dstY, long dstWidth, long dstHeight, CBitmapEx& bitmapEx, // long srcX, long srcY, long srcWidth, long srcHeight, long alpha); // void DrawTransparent(long dstX, long dstY, long width, long height, // CBitmapEx& bitmapEx, long srcX, long srcY, _PIXEL transparentColor=_RGB(0,0,0)); // void DrawTransparent(long dstX, long dstY, long width, long height, // CBitmapEx& bitmapEx, long srcX, long srcY, long alpha, // _PIXEL transparentColor=_RGB(0,0,0)); // void DrawTransparent(long dstX, long dstY, long dstWidth, long dstHeight, // CBitmapEx& bitmapEx, long srcX, long srcY, long srcWidth, long srcHeight, // _PIXEL transparentColor=_RGB(0,0,0)); // void DrawTransparent(long dstX, long dstY, long dstWidth, long dstHeight, // CBitmapEx& bitmapEx, long srcX, long srcY, long srcWidth, long srcHeight, // long alpha, _PIXEL transparentColor=_RGB(0,0,0)); // LPBI
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值