C++位图bitset的简单实现

文章介绍了如何在C++中使用bitset数据结构来实现位图,包括通过vector存储、set()、reset()和test()函数的详细实现方法,适用于海量数据的快速查找、去重和集合运算等场景。

C++位图bitset的简单实现

1.引言

在这里插入图片描述

​ 在计算机中,位图简单来说就是一串01序列,用每一位来存放某种状态。适用于海量数据、数据无重复的场景。通常都是用每一个位来判断在不在的一种模型。

具体使用场景包括但不限于:

​ 1.快速查找某个数据是否在一个集合中

​ 2. 排序 + 去重

​ 3. 求两个集合的交集、并集等

​ 4. 操作系统中磁盘块标记

​ 5.给40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何快速判断一个数是否在这40亿个数中。【腾讯】

2.实现思路

​ 由于在实际代码中为了方便对位进行操作,我们选择底层使用vector包含一个字节的char的vector数组来具体移动位置。

在这里插入图片描述

需要实现的简单功能有:
1.set(size_t x) 将该位置bit位设置为1

2.reset(size_t x)将该位置bit位设置为0

3.test() //检测该位置是为0还是1

3.具体实现

3.1类结构

template<size_t N>
	class BitSet
	{
	public:
		BitSet() //构造
		{
			_bits.resize(N / 8 + 1, 0);//+1是为了防止65/8,多开一个,防止少一个没加的
		}

		void set(size_t x)//set是将bit位置为1
		{}

		void reset(size_t x)//reset是将bit位置为0
		{}

		bool test() //检测该位是0还是1
		{}


	private:
		vector<char> _bits;
	};

3.2set()

先通过除的方法找到具体是哪一个char,再通过取模的方法具体找到char中的哪一个bit位。

然后用当前值**或‘|’**上1之后左移的具体位数。

例如: 原本是: 1101 1001 我想让从右至左的第六位变成1,则‘|’ 0010 0000

那么应该是:
1101 1001

​ ‘|’ 0010 0000

​ ==> 1111 1001

void set(size_t x)//set是将bit位置为1
		{
			size_t i = x / 8; // 找到所在的char个数的位置	
			size_t j = x % 8; // 找到所在char的具体bit位

			_bits[i] |= (1 << j); //左移    :1跟任何数|都是1

		}

3.3reset()

通过除的方法找到具体是哪一个char,再通过取模的方法具体找到char中的哪一个bit位。

再用当前值**与‘&’**上1左移j位后的取反

例如: 1101 1001 想让从右至左第五位置成0,则与 0001 0000的取反 1110 1111取余

​ 具体: 1101 1001

​ ‘&’ 1110 1111

​ ==> 1100 1001

void reset(size_t x)//reset是将bit位置为0
		{
			size_t i = x / 8;
			size_t j = x % 8;
			_bits[i] &= ~(1 << j); 
		}

3.4test()

​ 检测该位到底是0还是1,则与1左移后的j位与‘&’

bool test() //检测该位是0还是1
		{
			size_t i = x / 8;
			size_t j = x % 8;

			return _bits[i] & (1 << j);
		}

3.5测试

采用以下代码进行测试

void test()
	{
		BitSet<100> s; //将100bit中第10和11位置1
		s.set(10);
		s.set(11);


	}

如上,若对一个100位大小的位图中,第10位和第11位进行置1,那么按照一个char一个字节8bit,应该是在第2个char中,且第二个char中的bit位应该是0011 0000。由于编译器无法看bit位,只能看16进制的数,那么对应的应该是00 0c 00 00让我们具体调试看看是不是这个值。

在这里插入图片描述

我们找到这个起始地址,再从监视窗口看。

在这里插入图片描述

是这个值,说明一个简单的bit位图就制作好了。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Arthur___Cui

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值