数据结构:位图

所有比特的编号方法是,从低字节的低位比特位开始,第一个bit为0,最后一个bit为 2^(n-1)。

比如说,现在有个数组是这样子的,int a[4],那么
a[0]的比特位为0——31
a[1]的比特位为32——63
a[2]的比特位为64——95
a[3]的比特位为96——127

比如说现在我们有100这个数,于是,我们要将第100位置为1,也就是说,我们最少得有100位,100位等于12.5字节,因为一个int型是4个字节,所以我们必须定义一个这样的数组int[4],数组的位模型可以参考上面。现在,我们要对这个数组的100位进行置位操作,那首先我得先知道100是在这个数组中的第几个元素,所以,使用100/32,我现在要第100位,然后,每个数组元素是32位,进行运算之后,我就得到了我要置的位在那一个元素了,那确定了元素之后,我得知道,我要置位的是元素的哪一个位,所以我就得知道求余的结果,所以就100%32,得到要置位的位置了。

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

class BitMap
{
public:
    BitMap(size_t range)
    {
        _a.resize((range >> 5) + 1);//右移5位表示除以32
    }

    void Set(size_t value)//置1
    {
        size_t index = value / 32;
        size_t num = value % 32;
        _a[index] |= (1 << num);
    }

    void ReSet(size_t value)//置0
    {
        size_t index = value / 32;
        size_t num = value % 32;
        _a[index] &= (~(1 << num));
    }

    bool Test(size_t value)
    {
        size_t index = (value >> 5);
        size_t num = value % 32;
        return _a[index] & (1 << num);
    }//非0则存在
protected:
    vector<int> _a;
};

void TestBitMap()
{
    BitMap bm(-1);//全1
    bm.Set(1000);
    bm.Set(1005);
    bm.Set(1006);
    cout << bm.Test(1000) << endl;
}

这里写图片描述

如果把测试用例改为如下:

void TestBitMap()
{
    BitMap bm(-1);//全1
    bm.Set(1000);
    bm.Set(1005);
    bm.Set(1006);
    cout << bm.Test(1003) << endl;
}

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

位图的优缺点:
优点:
(1)速度快
(2)内存空间占用小
(3)能表示大范围的数据
缺点:
(1)可读性差
(2)位图存储的元素个数虽然比一般做法多,但是存储的元素大小受限于存储空间的大小。位图存储性质:存储的元素个数等于元素的最大值。比如, 1K 字节内存,能存储 8K 个值大小上限为 8K 的元素。(元素值上限为 8K ,这个局限性很大!)比如,要存储值为 65535 的数,就必须要 65535/8=8K 字节的内存。要就导致了位图法根本不适合存 unsigned int 类型的数(大约需要 2^32/8=5 亿字节的内存)。
(3)位图对有符号类型数据的存储,需要 2 位来表示一个有符号元素。这会让位图能存储的元素个数,元素值大小上限减半。 比如 8K 字节内存空间存储 short 类型数据只能存 8K*4=32K 个,元素值大小范围为 -32K~32K 。

位图的应用
1、给40亿个不重复的unsigned int的整数,没排过序的,然后再给一个数,如何快速判断这个数是否在那40亿个数当中
  首先,将这40亿个数字存储到bitmap中,然后对于给出的数,判断是否在bitmap中即可。
2、使用位图法判断整形数组是否存在重复
遍历数组,一个一个放入bitmap,并且检查其是否在bitmap中出现过,如果没出现放入,否则即为重复的元素。
3、使用位图法进行整形数组排序
首先遍历数组,得到数组的最大最小值,然后根据这个最大最小值来缩小bitmap的范围。这里需要注意对于int的负数,都要转化为unsigned int来处理,而且取位的时候,数字要减去最小值。
4、在2.5亿个整数中找出不重复的整数,注,内存不足以容纳这2.5亿个整数
参 考的一个方法是:采用2-Bitmap(每个数分配2bit,00表示不存在,01表示出现一次,10表示多次,11无意义)。其实,这里可以使用两个普 通的Bitmap,即第一个Bitmap存储的是整数是否出现,如果再次出现,则在第二个Bitmap中设置即可。这样的话,就可以使用简单的1- Bitmap了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
位图是一种用于存储和操作大量布尔值(true/false)的数据结构。在计算机科学中,位图通常被用于表示一个集合,其中每个元素都对应于一个(二进制),如果该元素在集合中,则对应的值为1,否则为0。使用位图可以极大地减少空间占用,并且可以快速进行一些集合操作,例如并集、交集、差集等。 在Python中,可以使用内置的`array`模块创建位图。该模块提供了一种称为“signed char”的数据类型,它只占用一个字节,可以存储8个布尔值。因此,我们可以将一个大的布尔数组压缩到相对较小的内存空间中。 下面是一个简单的示例,演示如何使用array模块创建一个位图,并执行一些基本操作: ```python import array # 创建一个包含100个布尔值的位图 bit_array = array.array('b', [0] * 100) # 设置第10个元素为True bit_array[9] = 1 # 检查第10个元素是否为True if bit_array[9]: print("第10个元素为True") # 计算位图中所有为True的元素的数量 count = sum(bit_array) print("位图中共有{}个元素为True".format(count)) ``` 注意,在上面的示例中,我们使用'b'作为数组的类型代码,表示signed char类型。这意味着每个元素只占用一个字节。如果我们需要存储更多的布尔值,可以尝试使用其他类型代码,例如'B'(unsigned char)或'i'(signed int)。但是要注意,使用更大的数据类型会占用更多的内存空间。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值