【C++】哈希之位图(详解)

目录

一,位图的概念 

二,位图的实现

1,插入

2,删除

3,查找

三,模拟实现


一,位图的概念 

在C++编程中,位图是一种常用的数据结构,用于高效地表示大量的布尔值。它通过使用一个二进制位来表示每个元素的存在与否,从而节省了大量的内存空间。

所谓位图,就是用每一位来存放某种状态,适用于海量数据,数据无重复的场景。通常是用 来判断某个数据存不存在的。

具体来说,位图由一组二进制位(0或1)组成,其中每个位代表一个元素的存在状态。

如果该位为1,则表示对应的元素存在;

如果该位为0,则表示对应的元素不存在。

通过这种方式,位图可以将大量的元素用较少的内存空间表示出来,从而提高了数据的处理效率。

在C++中,位图通常使用一个字符数组来表示。假设我们需要表示 n 个元素的存在状态,那么我们可以使用一个长度为 ( n / 8 + 1 ) 的整数数组来表示位图。其中,每个整数表示8个元素的存在状态。例如,如果第 i 个元素存在,则我们可以将第 i 个二进制位设置为1,并将其所在的整数存储在位图数组的第 i / 8 个位置上。

通过这种方式,我们可以快速地进行元素的插入、删除和查找操作。在插入一个元素时,我们只需要将相应的二进制位设置为1即可;在删除一个元素时,我们只需要将相应的二进制位设置为0即可;在查找一个元素时,我们只需要检查相应的二进制位是否为1即可

问题:

给定一个包含40亿个数的数据集合,我们需要快速判断一个特定的数是否存在于其中。如何有效地解决这个问题呢?

在海量数据里面快速判断一个特定的树是否存在其中,传统的线性搜索算法需要遍历整个数据集合,时间复杂度较高,无法满足实时性和高效性的要求。而位图算法则提供了一种更加优雅和高效的解决方案。通过将每个数映射到位图中的相应位置上,我们可以利用位运算来快速判断一个数是否存在

二,位图的实现

1,插入

1,计算索引:首先,需要确定要插入的元素在位图中对应的索引位置。通常情况下,位图使用字符数组来表示,每个整数可以表示8个元素的存在状态。因此,我们可以通过将元素的值除以8来计算它在整数数组中的索引。

int index= n / 8;

2,计算偏移量:接下来,需要确定要插入的元素在位图中对应的二进制位的偏移量。偏移量是指元素在整数中的二进制位的位置。我们可以通过将元素的值模8来计算偏移量。

int pos = n % 8;

3,设置二进制位:最后,通过使用位运算和按位或操作,将对应的二进制位设置为1,即将元素插入位图。

_bit[index] |= (1 << pos);

这里,(1 << pos) 表示将1左移pos位,得到一个只有第pos位为1的二进制数。然后,使用按位或操作符|=将这个二进制数与位图中对应索引的整数进行按位或运算,将对应的二进制位设置为1。

2,删除

1,计算索引:首先,需要确定要插入的元素在位图中对应的索引位置。通常情况下,位图使用字符数组来表示,每个整数可以表示8个元素的存在状态。因此,我们可以通过将元素的值除以8来计算它在整数数组中的索引。

int index= n / 8;

2,计算偏移量:接下来,需要确定要插入的元素在位图中对应的二进制位的偏移量。偏移量是指元素在整数中的二进制位的位置。我们可以通过将元素的值模8来计算偏移量。

int pos = n % 8;

3,清除二进制位:最后,通过使用位运算和按位与操作,将对应的二进制位设置为0,即将元素从位图中删除。

_bit[index] &= ~(1 << pos);

这里,~(1 << pos) 表示将1左移pos位,得到一个只有第pos位为0的二进制数,然后使用按位与操作符&=将这个二进制数与位图中对应索引的整数进行按位与运算,将对应的二进制位设置为0。

3,查找

1,计算索引:首先,需要确定要插入的元素在位图中对应的索引位置。通常情况下,位图使用字符数组来表示,每个整数可以表示8个元素的存在状态。因此,我们可以通过将元素的值除以8来计算它在整数数组中的索引。

int index= n / 8;

2,计算偏移量:接下来,需要确定要插入的元素在位图中对应的二进制位的偏移量。偏移量是指元素在整数中的二进制位的位置。我们可以通过将元素的值模8来计算偏移量。

int pos = n % 8;

3,检查二进制位:使用按位与操作符&将对应的二进制位提取出来,并检查其值是否为1。

int bit = _bit[index] & (1 << pos);

这里,(1 << pos) 表示将1左移pos位,得到一个只有第pos位为1的二进制数。然后,使用按位与操作符&将这个二进制数与位图中对应索引的char变量进行按位与运算,提取出对应的二进制位。

如果结果为0,则表示元素不存在于位图中。

如果结果不为0,则表示元素存在于位图中。

三,模拟实现

class bitset
{
public:
	bitset(size_t bitCount)
		: _bit((bitCount >> 5) + 1), _bitCount(bitCount)
	{}
	// 将which比特位置1
	void set(size_t which)
	{
		if (which > _bitCount)
			return;
		size_t index = (which >> 5);
		size_t pos = which % 32;
		_bit[index] |= (1 << pos);
	}
	// 将which比特位置0
	void reset(size_t which)
	{
		if (which > _bitCount)
			return;
		size_t index = (which >> 5);
		size_t pos = which % 32;
		_bit[index] &= ~(1 << pos);
	}
	// 检测位图中which是否为1
	bool test(size_t which)
	{
		if (which > _bitCount)
			return false;
		size_t index = (which >> 5);
		size_t pos = which % 32;
		return _bit[index] & (1 << pos);
	}
private:
	vector<int> _bit;
	size_t _bitCount;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

手法king

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

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

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

打赏作者

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

抵扣说明:

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

余额充值