【数据结构】位图

一、基本概念
在存储数据之时,如果按照其原数据类型存储数据,如果要存取大量数据之时,有可能会由于数据元素个数较多且类型较大,不能一次性存储,而采用位图,将极大的解决这个问题。
位图是利用数组,将数组下标与元素一一对应,将元素所在的这个比特位的状态改为存在,则可以表明这个元素的状态即可。
主要表示为如下:
这里写图片描述

二、代码实现

#include<iostream>
using namespace std;
#include<vector>

class BitSet
{
public:
    BitSet(size_t  size = 10)
        :_size(size)
    {
        _bt.resize(((size >> 5) + 1));//表示当前需要申请多少个int
    }
    void Set(int whichBit)
    {
        //计算当前值在申请的哪一个int上
        int index = (whichBit >> 5);
        //就算在当前int下的哪一个bit位上
        if (whichBit < _size)
            _bt[index] |= (1 << (whichBit % 32));//whichBit % 32计算当前数字在哪个bit位上,从而将相对应的比特位置为1
    }
    void ReSet(int whichBit)
    {
        //计算当前值在申请的哪一个int上
        int index = (whichBit >> 5);
        //就算在当前int下的哪一个bit位上
        if (whichBit < _size)
            _bt[index] &= ~(1 << (whichBit % 32));
    }
    //检测当前位是否为1
    bool Test(int whichBit)
    {
        //计算当前值在申请的哪一个int上
        int index = (whichBit >> 5);
        //就算在当前int下的哪一个bit位上

        if (whichBit < _size)
            return (_bt[index] & (1 << (whichBit % 32)));

        else
        {
            printf("whichbit error\n");
            return false;
        }
    }


    size_t Count()
    {
        /*int count = 0;
        for (size_t i = 0; i < _bt.size(); ++i)
        {
            int value = _bt[i];
            while (value)
            {
                ++count;
                value &= (value - 1);
            }
        }
        return count;*/

        //方法二,此种方法利用一次统计四个比特位,则其可能出现1的次数的一共有十六种情况,在此处可以利用字符串常量,将其给出
        char* pCount = "\0\1\1\2\1\2\2\3\1\2\2\3\2\3\3\4";//四个比特位,表明有十六种状态
        int count = 0;
        for (size_t i = 0; i < _bt.size(); ++i)//_bt.size()表示有多少个int
        {
            int value = _bt[i];//_bt为int型,此处取出其第一个int
            //在此处一次统计四个比特位
            int j = 0;
            while (j < sizeof(int))
            {
                count += pCount[value & 0x0F];//首先统计第一个四比特位
                value = value >> 4;//将刚才已经统计的四位移走,然后统计剩下的四位
                count += pCount[value & 0x0F];
                value = value >> 4;//此时已将第一个字节统计完成。
                ++j;
            }
        }
        return count;
    }
    //返回比特位的个数
    size_t Size()const
    {
        return _size;
    }
private:
    vector<int> _bt;//表示当前一次性申请多少个比特位,此时默认申请32位
    int _size;//表示已经使用了多少比特位
};

void TestBit()
{
    BitSet bt(100);
    bt.Set(36);
    bt.Set(76);
    bt.Set(69);
    bt.Set(45);
    bt.Set(450);
    cout << bt.Count() << endl;
    cout << bt.Size() << endl;

    if (bt.Test(76))
        cout << "是1" << endl;
    else
        cout << "不是1" << endl;

    bt.ReSet(36);
    bt.ReSet(45);
    cout << bt.Count() << endl;
    cout << bt.Size() << endl;
    if (bt.Test(36))
        cout << "是1" << endl;
    else
        cout << "不是1" << endl;
}

有关位图的应用,一般是在海量数据,表示一个元素是否存在,求两个集合或者多个集合的交集与并集等的情况中,应用的十分广泛。

希望今天的内容,可以帮助到大家!!!

只有不停的奔跑,才能不停留在原地!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值