搜索结构——布隆过滤器

引:40亿个字符串集合,快速判断某个字符串是否存在

 位图适用于整形,布隆过滤器适用于任何类型;

什么是布隆过滤器

本质上布隆过滤器是一种数据结构,比较巧妙的概率型数据结构(probabilistic data structure),特点是高效地插入和查询,可以用来告诉你 “某样东西一定不存在或者可能存在”。

相比于传统的 List、Set、Map 等数据结构,它更高效、占用空间更少,但是缺点是其返回的结果是概率性的,而不是确切的。

实现原理

HashMap 的问题

讲述布隆过滤器的原理之前,我们先思考一下,通常你判断某个元素是否存在用的是什么?应该蛮多人回答 HashMap 吧,确实可以将值映射到 HashMap 的 Key,然后可以在 O(1) 的时间复杂度内返回结果,效率奇高。但是 HashMap 的实现也有缺点,例如存储容量占比高,考虑到负载因子的存在,通常空间是不能被用满的,而一旦你的值很多例如上亿的时候,那 HashMap 占据的内存大小就变得很可观了。

还比如说你的数据集存储在远程服务器上,本地服务接受输入,而数据集非常大不可能一次性读进内存构建 HashMap 的时候,也会存在问题。

布隆过滤器数据结构

当我们判断一个字符是否存在首先想到的就是平衡搜索树或者哈希,但是40亿个字符串占太多空间,所以采用位图,那么我们需要字符串哈希算法函数将字符串转化为整数,判断位图对应位置是否为1;但是这样存在一个问题就是误判:对应位置为1,字符串可能不存在;对应位置为0,字符串一定不存在。因为可能存在冲突。针对这一问题,布隆过滤器并没有解决这一问题,而是降低冲突的发生概率。那么怎么处理的呢?布隆过滤器是通过多个字符串哈希函数映射出不同的地址,所以这样可以有效地降低冲突的发生。那么问题来了,选择多少个函数合适呢,这个不可以多,也不可以少。

支持删除么

目前我们知道布隆过滤器可以支持 add 和 isExist 操作,那么 delete 操作可以么,答案是不可以,例如上图中的 bit 位 4 被两个值共同覆盖的话,一旦你删除其中一个值例如 “tencent” 而将其置位 0,那么下次判断另一个值例如 “baidu” 是否存在的话,会直接返回 false,而实际上你并没有删除它。

如何解决这个问题,答案是计数删除。但是计数删除需要存储一个数值,而不是原先的 bit 位,会增大占用的内存大小。这样的话,增加一个值就是将对应索引槽上存储的值加一,删除则是减一,判断是否存在则是看值是否大于0。

猜你喜欢

转载自blog.csdn.net/weixin_41318405/article/details/87009867