【位图】的实现和应用

一、位图

所谓bitmap,就是用每一位来存放某种状态,适用于大规模数据,但数据状态又不是很多的情况。通常是用来判断某个数据存不存在的。
在这里我们可以借助vector作为位图底层实现载体,具体实现方式如下:

#pragma once
#include<vector>
#include<iostream>
using namespace std;
class BitMap
{
public:
    BitMap(size_t bitSet = 10)
        :_bitsize(bitSet)
    {
        _bit.resize((bitSet >> 5)+1);
    }

    void Set(size_t BitPos)//指定bit置1
    {
        size_t index = (BitPos >> 5);//定位到具体的int中
        if (index<_bitsize)
            _bit[index] |= 1 << (BitPos % 32);
    }

    void SetZero(size_t BitPos)//指定比特位置0
    {
        size_t  index = BitPos >> 5;
        if (index < _bitsize)
            _bit[index] &= ~(1 << (BitPos % 32));
    }

    bool Isone(size_t BitPos)//判断指定比特位是否为1
    {
        size_t index = BitPos >> 5;
        if (BitPos < _bitsize)
            return _bit[index] & (1 << (BitPos % 32));
        cout << "当前比特位不存在" << endl;
        return false;
    }

    size_t CountOf1()const//计算比特位中1的个数
    {
        char* pBitCount = "\0\1\1\2\1\2\2\3\1\2\2\3\2\3\3\4";
        size_t count = 0;
        for (int i = 0; i < _bit.size(); ++i)
        {
            int value = _bit[i];
            int j = 0;
            //处理一个int
            while (j < sizeof(int))
            {//处理一个字节中1的个数
                count += pBitCount[value & 0X0F];
                value >>= 4;
                count += pBitCount[value & 0X0F];
                value >>= 4;
                ++j;
            }
        }
        return count;
    }

    size_t  Size()//位图的位数
    {
        return _bitsize;
    }
private:
    std::vector<int> _bit;
    size_t _bitsize;//总的比特位的个数
};

测试函数:

void TestBitMap()
{
    BitMap bt(100);
    bt.Set(12);
    bt.Set(45);
    bt.Set(56);
    bt.Set(66);
    cout << "位集合中1的个数:" << bt.CountOf1() << endl;
    cout << "比特位的个数是:" << bt.Size() << endl;
    if (bt.Isone(12))
        cout << "12号位置为1" << endl;
    else
        cout << "12号位置不为1" << endl;
    bt.SetZero(66);
    cout << "位集合中1的个数:" << bt.CountOf1() << endl;
    cout << "比特位的个数是:" << bt.Size() << endl;
    if (bt.Isone(50))
        cout << "50号位置为1" << endl;
    else
        cout << "50号位置不为1" << endl;

}
int main()
{
    TestBitMap();
    system("pause");
    return 0;
}

运行结果验证:
这里写图片描述

二、位图的应用

1、给定100亿个整数,设计算法找到只出现一次的整数 。

解决思路:将100亿个数分拆成1000份文件,再将每份文件里使用位图,并用两位bit表示数字出现的次数,00存出现0次的数,01存放出现1次的数,10存放出现多次的数,11舍弃,再将1000份中出现一次的数全部合并到一个文件里存放即可。

2、给两个文件,分别有100亿个整数,我们只有1G内存,如何找到两个文件交集

解决方法:扫描每个整数是否出现过,节省内存方法使用bitmap。用两位bit表示数字出现的次数,00表示文件均没出现,10表示文件1出现过,01表示文件2出现过,11表示两文件均出现过,共需要2^32*2/8 = 1GB内存,遍历两个文件中的所有整数,然后寻找bitmap中11对应的整数即是两个文件的交集,这样即可线性时间复杂度完成。

3、1个文件有100亿个int,1G内存,设计算法找到出现次数不超过2次的所有整数

解决方法:将100亿个数分拆成1000份文件,再将每份文件里使用位图,并用两位bit表示数字出现的次数,00存出现0次的数,01存放出现1次的数,10存放出现2次的数,11舍弃,再将1000份中出现次数不超过二的数全部合并到一个文件里存放即可

4、给两个文件,分别有100亿个query,我们只有1G内存,如何找到两个文件交集?分别给出精确算法和近似算法?

精确算法:
将两个文件分别存入相同哈希算法的1000个哈希桶(共两千个)文件,再在每个文件找出相同的query
近似算法:
因为文件可能大部分都是字符,所以不能用位图处理,即利用布隆过滤器进行比较(布隆过滤器:其实就是一张用来存储字符串hash值的BitMap.)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值