bloom 算法

该文章翻译自 (https://www.enjoyalgorithms.com/blog/bloom-filter/)[https://www.enjoyalgorithms.com/blog/bloom-filter/]

Bloom 过滤器是一种空间效率高的概率数据结构,它能告诉我们某个元素可能在某个集合中,或者肯定不在某个集合中。如果我们在Bloom 过滤器中查找一个项,可以得到两种可能的结果。

  • 这个项肯定不在这个集合中,真否定
  • 项目可能存在于集合中,可以是徦阳性或真阳性,

Bloom 过滤器如何工作?

假设我们要比较两个字符串。我们不需要存储整个字符串,而是计算字符串的哈希值,然后比较哈希值,计算哈希值然后比较他们需要 O(1) 时间,而直接比较字符串需要 O(n) 时间,如果两个哈希值不相等,我们就可以肯定的说字符串不相等,否则两个字符串可能相等!

这种方法的一个缺点是哈希函数的范围有限。散列函数 h1 的范围从 0 - r1-1.由于至少有两个字符串的哈希值相同,因此我们无法用这种方法唯一识别 r1 以上个字符串,为了弥补这一缺陷,我们可以使用多个散列函数。

假设我们使用 k 个哈希函数 h1,h2,...hk ,将两个字符串通过这些哈希函数,并计算他们的哈希值。如果两个字符的所有哈希值都相同,那么这两个字符串相同的概率就会非常高。另一方面,即使有一个哈希值不匹配,我们也可以说这两个字符串是不同的。

Bloom 过滤器是一个存储 0 和 1 的数组.

在 Bloom 过滤器中插入一个项目

要添加一个元素,我们需要通过 k 个哈希函数,比特将根据数组中散列的索引进行设置,例如我们要添加单词 "coding"

h1("coding") = 125

h2("coding") = 67

h3("coding") = 19

假设 Bloom 过滤器的大小为 m = 10, 我们需要对每个值取 10 的模,以便索引在 Bloom 过滤器的范围内。因此,必须将 125%10 = 5, 67%10 = 7 和 19%10=9 .然后把对应的 bit 设置为 1.

测试某个项是否在集合中

如果我们想要测试某个元素是否在集合中,就需要通过相同的哈希函数。如果所有这些索引的 bit 都已被设置为 1,那么这个元素就可能存在于集合中。不过,即使有一个 bit 没有被设置,我们可以肯定的说这个元素不存在于集合中。

假设我们要检查 "cat" 是否在集合中。我们先在之前添加了 "coding" 和 "music" 两个元素。

coding 的三个哈希函数输出为 {125,67,19} ,那么索引 {5,7,9} 设置为 1

music 的三个哈希函数输出为 {290,45,2}, 那么索引 {0,2,5} 就会设置为 1.

那么 bloom 过滤器现在的值就是

[1,0,1,0,0,1,0,1,0,1]

我们将 "cat" 通过相同的哈希函数,得到如下结果:

h1("cat") = 233

h2("cat") = 155

h3("cat") = 9

因此我们检查索引 {3,5,9}是否都设置为 1,我们可以看到尽管索引 5 和 9 都设置为 1,但是 3 却没有,因此我们可以百分百确定,"cat" 肯定不会在这个集合中

现在我们要检查一下 "gaming" ,我们继续通过相同的哈希函数得到如下结果:

h1("gaming") = 235

h2("gaming") = 60

h3("gaming") = 22

我们检查索引 {0,2,5} 是否都设置为 1,我们可以看到,所有这些索引都设置为 1,然而,我们知道 "gaming" 并不在这个集合中,因此这是一个假阳性。同时我们可以计算一下错误的概率,(参看原文)。我们可以看到如果 m 趋于无情大,错误率就会趋于零。另一种避免高误判率的方法是使用多个哈希函数。

Bloom 过滤器的作用

Bloom 过滤器可作用于第一层过滤,它的优点是不占用太多空间,当我们想知道某些东西是肯定不存在或是可能存在时,就可以用它

Medium 在其推荐模块中使用 bloom 过滤器,避免显示用户以及看过的帖子。

posted @ 2024-03-20 11:44  ZARD_Fans  阅读(9)  评论(0编辑  收藏  举报