哈希位图与布隆过滤器

gitbub源码链接https://github.com/duchenlong/Cpp/tree/master/hash_bit/hash_bit

哈希位图

在之前的哈希表中,我们采用一个基本数据类型表示一个数据。就像一个int类型的数据,它占用了4个字节表示一个数据,但是当数据量很大的时候.

  • 比如说42亿个数据类型,他的大小就是4G * 4 = 16G,这时候我们直接开辟这么大的空间显然是不合理,因为32位系统下虚拟内存一共才4G

因为一个字节时8位,那么我们是否可以用一个位来表示一个数据呢?
在这里插入图片描述

位图的概念

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

实现方法

类似于哈希的思想,先列一个框架

template<class T>
class HashBit
{
public:
	HashBit(size_t N)
	{
		_table.resize(N / 32 + 1, 0);// +1 防止出现 33 / 32 = 1,的遗留问题
		_num = 0;
	}
private:
	vector<int> _table;
	size_t _num = 0;
};

我们在一开始初始化的时候,就直接把这个位图开辟为需要的大小。这里需要注意,我们使用的数据类型为int,他是4个字节,也就是32位

那么我们开辟数组的大小就是(N / 32 + 1),至于为什么需要 +1,因为计算机中的除法是那种整除,会把余数舍去,所以+1就是为了避免舍去的余数而造成的越界访问的问题。

中间我们还需要加入一个增加,删除,判断该数是否存在的函数

  1. 增加一个数(给表示该数的位置1)

首先我们先确定这个数的位置

	size_t idx = num / 32;//确定在数组那一个下标位置
	size_t pos = num % 32;//确定偏移量

然后我们就把这个位置置1就行了,采用的是的方式

	//num 数的位置 置1
	void set(size_t num)
	{
		size_t idx = num / 32;
		size_t pos = num % 32;

		_table[idx] |= (1 << pos);
	}
  1. 删除一个数据(表示该数的位置置0

同理,我们先找到这个数位,然后把这个位置置1,采取的方式为的方式,把该位置置0,然后其他位置为全1。

	//num 数的位置 置0
	void reset(size_t num)
	{
		size_t idx = num / 32;
		size_t pos = num % 32;

		//_table[idx] = ((_table[idx] | (1 << pos)) ^ (1 << pos));

		_table[idx] &= ~(1 << pos);
	}
  1. 判断这个数字是否存在

判断该标志位是否为1

	//num 数是否存在数组中
	bool test(size_t num)
	{
		size_t idx = num / 32;
		size_t pos = num % 32;

		return _table[idx] & (1 << pos);
	}

布隆过滤器

在这里插入图片描述
我们在CSDN上看文章的时候,在首页的推荐页面中,基本上是很难看到一篇重复的文章。这在他的底层是需要有一个去重的过程的,那么他的底层会是一个什么结构来去重呢?

  • 哈希表存储,就是有点浪费空间
  • 哈希位图,不容易处理哈希冲突的问题
  • 哈希表与位图结合,布隆过滤器

布隆过滤器的概念

布隆过滤器(Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数

布隆过滤器可以用于检索一个元素是否在一个集合中

  • 优点是 ,空间效率和查询时间都比一般的算法要好的多
  • 缺点是,有一定的误识别率和删除困难

在这里插入图片描述

布隆过滤器的实现

因为布隆过滤器的原理就是,利用了多个不同的哈希函数来计算插入位置,插入一个数据的时候,其实等于说是插入了多次。

这样当我们进行判断该元素在不在的时候,只需要分别根据这几个哈希函数计算的位置来判断就可以了,

  • 只要有一个位置存在数据,那么该数据可能存在;
  • 如果有一个位置没有数据,那么该数据一定不存在

所以说布隆过滤器判断数据是否存在,是一个概率事件。但是当判断出一个数据不在的时候,这个数据一定不在原始数据中。

布隆过滤器的大体框架(这里使用了三个哈希函数,所以一开始开辟空间的时候为开辟三倍的空间)

template<class K = string,class Hash1 = HashStr1,
				class Hash2 = HashStr2,class Hash3 = HashStr3>
	class bloomFilter
	{
	public:
		bloomFilter(size_t num)
			:_bs(num * 3)
		{}
	private:
		HashBit _bs;
	};
  1. 插入元素

在这里插入图片描述
同时对这三个哈希函数计算的插入位置,进行插入该元素

	void set(const K& key)
	{
		size_t idx1 = Hash1()(key);
		size_t idx2 = Hash2()(key);
		size_t idx3 = Hash3()(key);

		_bs.set(idx1);
		_bs.set(idx2);
		_bs.set(idx3);
	}
  1. 判断一个数据是否存在

布隆过滤器如果说某个元素不存在时,该元素一定不存在,如果该元素存在时,该元素可能存在,因为有些哈希函数存在一定的误判。

	bool test(const K& key)
	{
		size_t idx1 = Hash1()(key);
		if (_bs.test(idx1) == false)
			return false;
			
		size_t idx2 = Hash2()(key);
		if (_bs.test(idx2) == false)
			return false;
			
		size_t idx3 = Hash3()(key);
		if (_bs.test(idx3) == false)
			return false;

		return true;
	}

最后,布隆过滤器是不支持删除操作的,因为在删除一个元素的时候,可能会影响到其他真实存在的元素。

是否会存在这样一种情况,就是有一个数据被布隆过滤器进行了误判,它本身是不存在的。然后对他进行删除的时候,就会删除掉该位置本身真实存在的数据。

所以说删除操作是有缺陷的,不可取。

布隆过滤器的优缺点

优点:

  1. 增加和查询的时间复杂度为O(K),K为哈希函数的个数
  2. 布隆过滤器不需要存储元素本身,在某些对保密要求比较严格的场合有很大优势
  3. 在能够承受一定的误判时,布隆过滤器比其他数据结构有这很大的空间优势
  4. 使用布隆过滤器,可以进行交,并,差集的运算
  5. 可以处理大数据的一些情况,百亿数据这种

缺点:

  1. 存在误判,可能会把一些不存在的数据,判断为存在
  2. 不能获取数据元素本身,只能完成从数据到哈希的映射,不能从哈希的位置到数据进行映射。
  3. 不支持删除元素
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值