首页
▼ 算法合集
▼ 加密算法
▼ 凯撒密码
凯撒密码
▼ Hill密码算法
Hill密码算法
▼ 多项式哈希算法
多项式哈希算法
▼ Rail Fence Cipher
Rail Fence Cipher
▼ Graph算法
▼ 关节点
关节点
▼ Bellman-Ford算法
Bellman-Ford算法
▼ 广度优先搜索
广度优先搜索
▼ GraphBridges
桥接模式
▼ 深度优先搜索
深度优先搜索
▼ 检测循环
检测循环
▼ Dijkstra算法
Dijkstra算法
▼ Eulerian Path
欧拉路径
▼ Floyd-Warshall算法
Floyd-Warshall算法
▼ HamiltonianCycle
Hamiltonian Cycle
▼ Kruskal算法
Kruskal算法
▼ Prim算法
Prim算法
▼ 强连通分量
强连通分量
▼ 拓扑排序
拓扑排序
▼ Travelling Salesman Problem
Travelling Salesman
▼ 图像处理算法
▼ Seam Carving算法
内容感知缩放算法
▼ 链表
▼ 反向遍历
反向遍历
▼ GraphTraversal
GraphTraversal
▼ 数学算法
▼ 二进制浮点数
BinaryFloatingPoint
▼ 位操作
位操作算法
▼ 复数
复数
▼ 欧几里得算法
Euclidean Algorithm
▼ Euclidean Distance
欧几里得距离
▼ 阶乘算法
阶乘算法
▼ 快速幂算法
快速幂算法
▼ Fibonacci数列
斐波那契数列
▼ 傅里叶变换
Fourier变换
▼ Horner法
霍纳法则
▼ 整数划分
整数划分
▼ 判断是否为2的幂
判断是否为2的幂
▼ 最小公倍数
最小公倍数
▼ Liu Hui
Liu Hui
▼ 矩阵
Matrix
▼ Pascal三角形
Pascal三角形
▼ Primality Test
素数测试
▼ 质因数
质因数
▼ 弧度计算
弧度计算
▼ 埃拉托色尼筛法
埃拉托色尼筛法
▼ SquareRoot
SquareRoot
▼ MachineLearning
▼ K均值算法
K均值算法
▼ K近邻算法
K近邻算法
▼ 搜索算法
▼ 二分查找算法
二分查找
▼ 插值搜索算法
插值搜索算法
▼ 跳跃搜索算法
跳跃搜索算法
▼ 线性搜索
线性搜索算法
▼ 集合
▼ 笛卡尔积
笛卡尔积
▼ 组合总和
组合总和
▼ 组合算法
组合算法
▼ Fisher-Yates洗牌算法
Fisher-Yates洗牌算法
▼ 背包问题
背包问题
▼ 最长公共子序列
最长公共子序列
▼ 最长递增子序列
最长递增子序列
▼ 最大子数组
最大子数组
▼ 排列组合
排列组合
▼ 幂集
幂集算法
▼ 最短公共超序列
最短公共超序列
▼ Sorting Algorithms
▼ 冒泡排序
冒泡排序
▼ 桶排序算法
桶排序算法
▼ 计数排序算法
计数排序
▼ 堆排序算法
堆排序
▼ 插入排序
插入排序
▼ 归并排序
归并排序
▼ 快速排序算法
快速排序算法
▼ 基数排序
基数排序
▼ 选择排序算法
选择排序算法
▼ 希尔排序
希尔排序
▼ 统计学
▼ 加权随机
加权随机算法
▼ 字符串算法
▼ Hamming距离
Hamming距离
▼ KnuthMorrisPratt算法
Knuth-Morris-Pratt算法
▼ LevenshteinDistance
Levenshtein距离
▼ 最长公共子串
最长公共子串
▼ 回文检测算法
回文检测算法
▼ Rabin-Karp算法
Rabin-Karp算法
▼ 正则表达式匹配
正则表达式匹配
▼ Z算法
Z算法
▼ Tree Data Structure
▼ 广度优先搜索
广度优先搜索
▼ 深度优先搜索
深度优先搜索
▼ 未分类
▼ 最佳买卖股票时机
最佳买卖股票时机
▼ 汉诺塔算法
HanoiTower
▼ 跳跃游戏算法
跳跃游戏
▼ KnightTour
骑士巡逻
▼ N皇后问题
N皇后问题
▼ 雨水收集
雨水收集
▼ 递归楼梯问题
递归楼梯问题
▼ 方阵旋转
方阵旋转
▼ 独特路径
UniquePaths
▼ 数据结构
▼ BloomFilter算法
布隆过滤器
▼ 不相交集数据结构
Disjoint Set
▼ 双向链表
双向链表
▼ Graph
Graph算法
▼ 哈希表
哈希表
▼ Heap数据结构
Heap数据结构
▼ 链表
链表
▼ LRU缓存
LRU缓存
▼ 优先队列
优先队列
▼ 队列
队列
▼ 栈结构
栈结构
▼ Tree Data Structure
树结构
▼ AVL树
AVL树
▼ 二叉搜索树
二叉搜索树
▼ Fenwick树
Fenwick树
▼ 红黑树
红黑树
▼ 线段树
SegmentTree
▼ Trie数据结构
Trie数据结构
布隆过滤器
在其他语言中阅读:
俄语(README.ru-RU.md|
葡萄牙语(README.pt-BR.md|
乌克兰语(README.uk-UA.md)
布隆过滤器是一种空间高效的概率数据结构,用于测试一个元素是否存在于集合中。它的设计目标是快速且使用最少的内存,但代价是潜在的误报。误报匹配是可能的,但误报不可能发生——换句话说,查询要么返回“可能存在于集合中”,要么返回“肯定不在集合中”。
布隆提出的这项技术适用于源数据量会因为应用“传统”无错误哈希技术而需要大量内存的情况。
算法描述
一个空的布隆过滤器是一个由m
位组成的比特数组,所有位都设置为0
。还必须定义k
个不同的哈希函数,每个哈希函数都将集合中的一个元素映射到m
数组位置之一,生成均匀随机分布。通常,k
是一个常数,远小于m
,m
与要添加的元素数量成正比;k
的确切选择和m
的比例常数由过滤器的预期误报率决定。
这里有一个布隆过滤器的例子,代表集合{x, y, z}
。彩色箭头显示了每个集合元素在比特数组中的位置。元素w
不在集合{x, y, z}
中,因为它哈希到一个包含0
的比特数组位置。对于这个图,m = 18
和k = 3
。

操作
布隆过滤器可以执行两个主要操作:插入(insertion)和搜索(search)。搜索可能会导致误报。无法删除。
换句话说,过滤器可以接受项目。当我们检查一个项目是否之前已经插入时,它可以告诉我们“没有”或者“可能”。
插入和搜索都是O(1)
操作。
创建过滤器
布隆过滤器是通过分配一定大小来创建的。在我们的例子中,我们使用100
作为默认长度。所有位置都被初始化为false
。
插入
在插入过程中,使用k
个哈希函数(在我们的例子中是3
个哈希函数)来创建输入的哈希值。这些哈希函数输出索引。在收到的每一个索引上,我们只需将布隆过滤器中的值更改为true
。
搜索
在搜索过程中,调用相同的哈希函数并用于哈希输入。然后我们检查收到的索引中是否有true
的值。如果有true
的值,我们就知道布隆过滤器可能之前插入过该值。
然而,我们不能确定这一点,因为其他之前插入的值可能会翻转这些值为true
。由于当前正在搜索的项目,值不一定为true
。除非只插入了一个项目,否则绝对确定性是不可能的。
在检查我们的哈希函数返回的索引时,如果其中任何一个值为false
,我们就可以肯定地知道该项目之前没有被插入。
误报
误报的概率由三个因素决定:布隆过滤器的大小、我们使用的哈希函数的数量以及已插入过滤器的项目数量。
计算误报概率的公式是:
( 1 - e -kn/m ) k
k
= 哈希函数的数量
m
= 过滤器大小
n
= 已插入项目的数量
这些变量k
、m
和n
应该根据对误报的接受程度来选择。如果选择了这些值,并且得到的概率太高,那么应该调整这些值并重新计算概率。
应用
布隆过滤器可以用于博客网站。如果目标是只向读者展示他们从未见过的文章,那么布隆过滤器是完美的。它可以基于文章存储哈希值。用户在阅读了一些文章后,可以将它们插入到过滤器中。下次用户访问网站时,这些文章可以从结果中过滤掉。
一些文章不可避免地会被错误地过滤掉,但这种成本是可以接受的。只要用户每次访问网站时都能看到其他全新的文章,即使他们错过了几篇文章也是可以接受的。
参考资料