布隆过滤器Bloom-Filter

相关概念知识

概念:布隆过滤器是一种紧凑型的、比较巧妙的概率型数据结构,特点是高效地插入和查询,可以用来告诉你 “某样东西一定不存在或者可能存在”,它是用多个哈希函数,将一个数据映射到位图结构中。此种方式不仅可以提升查询效率,也可以节省大量的内存空间。

实质:将哈希与位图结合,即布隆过滤器。

布隆过滤器优点

  1. 增加和查询元素的时间复杂度为:O(K), (K为哈希函数的个数),与数据量大小无关
  2. 哈希函数相互之间没有关系,方便硬件并行运算
  3. 在能够承受一定的误判时,布隆过滤器比其他数据结构有这很大的空间优势

布隆过滤器缺陷

  1. 有误判率,即不能准确判断元素是否在集合中
  2. 不能获取元素本身
  3. 一般情况下不能从布隆过滤器中删除元素

具体操作

插入:将要插入的数据经过K个哈希函数计算后,将位图里这些对应的哈希值的位置逐个置为1,也就是会有K个位置被置为1。
查找:将要查找的数据经过K个哈希函数计算后,去位图里的对应的哈希值的位置逐个查找,如果有其中一个是0,则肯定不存在,如果全是1,则大概率存在(因为某些1可能是其他数据置的1)。所以哈希函数越多,查找的准确率越高
删除:因为删除可能会删掉其他数据的1,从而导致数据错误,所以布隆过滤器是没有删除操作的

源码

布隆过滤器要用到的位图

class BitMap
{
private:
	vector<int> _table;
public:
	BitMap(size_t range)
	{
		//>>5是因为:一个字节32位,>>5相当于除以32。+1是因为:如果不是32的倍数,多出来的也要计算,例如33/32 =1,实际应该要2个字节来算
		_table.resize((range >> 5) + 1);
	}
	void set(int data)
	{
		//算出数组的下标
		size_t int_index = data >> 5;
		//算出一个字节里的比特位位置
		size_t bit_index = (data % 32);
		//或上1,就表示有这个数了
		_table[int_index] |= (1 << bit_index);
	}
	bool find(int data)
	{
		//算出数组的下标
		size_t int_index = data >> 5;
		//算出一个字节里的比特位位置
		size_t bit_index = (data % 32);
		//看那一比特位是否是1
		return ((_table[int_index] >> bit_index) & 1);
	}
	void reset(int data)
	{
		//算出数组的下标
		size_t int_index = data >> 5;
		//算出一个字节里的比特位位置
		size_t bit_index = (data % 32);
		//将那一位与0,其他位这时是与的1(但是与1对其他位没影响)
		_table[int_index] &= ~(1 << bit_index);
	}
};

哈希函数(这里只写了三个,可以再增加)

struct Hfun1
{
	size_t operator()(const string& str)
	{
		size_t hash = 0;
		for (const auto& ch : str)
		{
			hash = hash * 131 + ch;
		}
		return hash;
	}
};
struct Hfun2
{
	size_t operator()(const string& str)
	{
		size_t hash = 0;
		for (const auto& ch : str)
		{
			hash = hash * 65599 + ch;
		}
		return hash;
	}
};
struct Hfun3
{
	size_t operator()(const string& str)
	{
		size_t magic = 0;
		size_t hash = 0;
		for (const auto& ch : str)
		{
			hash = hash * magic + ch;
			magic *= 378551;
		}
		return hash;
	}
};

布隆过滤器

template<class K,class Hfun1,class Hfun2,class Hfun3>
class BloomFilter
{
private:
	BitMap _bm;
	size_t _bit_num;
public:
	BloomFilter(size_t range)
		:_bm(range * 5)//因为是多个映射,所以冲突的概率大,所以要多开一些
		, _bit_num(range * 5)
	{ }
	void set(const K& key)
	{
		//计算出各个哈希函数的位置
		size_t index1 = Hfun1()(key) % _bit_num;
		size_t index2 = Hfun2()(key) % _bit_num;
		size_t index3 = Hfun3()(key) % _bit_num;
		//插入到对应的位图位置
		_bm.set(index1);
		_bm.set(index2);
		_bm.set(index3);
	}
	bool test(const K& key)
	{
		//计算出各个哈希函数的位置
		size_t index1 = Hfun1()(key) % _bit_num;
		size_t index2 = Hfun2()(key) % _bit_num;
		size_t index3 = Hfun3()(key) % _bit_num;
		//逐个检查每个对应比特位是否是1,是1则可能存在,是0则肯定不存在
		if (_bm.find(index1) == false)
		{
			return false;
		}
		if (_bm.find(index2) == false)
		{
			return false;
		}
		if (_bm.find(index3) == false)
		{
			return false;
		}
		//虽然返回true了,但是也只是有可能存在,因为有些位图的1可能是其他的数据映射的
		return true;
	}
};

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值