《代码的未来》读书笔记——布隆过滤器

代码的未来布隆过滤器是一种可以判断某个数据是否存在的数据结构,或者也可以说是判断集合中是否包含某个成员的数据结构。布隆过滤器的特点如下:

  • 判断时间与数据个数无关(O(1))
  • 空间效率非常好
  • 无法删除元素
  • 偶尔会出错(!)

“偶尔会出错”这一条貌似违背了我们关于数据结构的常识,不过面对大量数据时,我们的目的是缩小查找的范围,因此大多数情况下,少量的误判并不会产生什么问题。

此外,布隆过滤器的误判都是假阳性(false positive),也就是说只会将不属于该集合的元素判断为属于该集合,而不会产生假阴性(false negative)的误判。像布隆过滤器这样“偶尔会出错”的算法,被称为概率算法(probabilistic algorithm)。

布隆过滤器不但拥有极高的时间效率(O(1)),还拥有极高的空间效率,理论上说(假设误判率为1%),平均每个数据只需要9.6比特的空间。包括散列表在内,其他表示集合的数据结构中都需要包含原始数据,相比之下,这样的空间效率简直是压倒性的。

布隆过滤器使用k个散列函数和m比特的比特数组(bit array)。作为比特数组的初始值,所有比特位都被置为0。向布隆过滤器插入数据时,会对该数据求得k个散列值(大于0小于m),并以每个散列值为索引,将对应的比特数组中的比特位全部置为1。

要判断布隆过滤器中是否包含某个数据,则需求得数据的k个散列值,只要其对应的比特位中有任意一个为0,则可以判断集合中不包含该数据。

即便所有k个比特都为1,也可能是由于散列冲突导致的偶然现象而已,这种情况下就产生了假阳性。假阳性的发生概率与集合中的数据个数n、散列函数种类数k,以及比特数组的大小m有关。如果m相对于n太小,就会发生比特数组中所有位都为1,从而将所有数据都判定为阳性的情况。

此外,当k过大时,每个数据所消耗的比特数也随之增加,比特数组填充速度加快,也是引发误判。相反,当k过小时,比特数组的填充进度速度较慢,但又会由于散列冲突的增多而导致误判的增加。

在信息爆炸所引发的大规模数据处理中,像布隆过滤器这样的算法,应该会变得愈发重要。

P169

 

发表评论

您的电子邮箱地址不会被公开。