详解布隆过滤器(含面试考点)

news2024/10/7 8:20:21

Bloom Filter

  • 底层逻辑
  • 主要代码实现解析(以C++为例)
  • 优缺点
  • 应用场景
  • 面试常问
    • 问题1:什么是布隆过滤器?
    • 问题2:布隆过滤器如何处理误报?
    • 问题3:如何设计布隆过滤器以最小化误报率?
    • 问题4:布隆过滤器有哪些应用场景?
    • 问题5:布隆过滤器与哈希表有什么区别?
    • 问题6:布隆过滤器在插入元素后,其准确性主要体现在哪些方面?
    • 问题7:布隆过滤器的原理是什么?
    • 问题8:布隆过滤器如何处理哈希碰撞?
    • 问题9:在什么情况下不适合使用布隆过滤器?

底层逻辑

在这里插入图片描述

位数组:布隆过滤器使用一个很长的二进制位数组(bit array)来存储数据。这个数组的每个位置(bit)初始时都被设置为0。

哈希函数:布隆过滤器使用多个哈希函数(通常是k个不同的哈希函数)。每个哈希函数都能将输入的元素映射到位数组的某个位置上。具体来说,每个哈希函数会对元素进行哈希运算,并产生一个哈希值。这个哈希值会被模(取余)运算后,得到一个在位数组范围内的索引,该索引就是元素在位数组中的位置。

插入元素:当需要插入一个元素时,会用这个元素去计算k个哈希值,得到k个索引。然后,将位数组中这k个索引位置上的值都设置为1。

查询元素:当需要查询一个元素是否存在于集合中时,同样会用这个元素去计算k个哈希值,得到k个索引。然后,检查位数组中这k个索引位置上的值是否都为1。如果都为1,则认为该元素可能存在于集合中(注意是“可能”,因为存在哈希冲突的可能性);如果至少有一个为0,则确定该元素不存在于集合中。

主要代码实现解析(以C++为例)

这里提供一个简化的布隆过滤器实现示例:

#include <iostream>
#include <bitset>
#include <functional> // for std::hash

class BloomFilter {
private:
    std::bitset<1000000> bitArray; // 位数组,假设大小为1000000
    std::hash<std::string> hashFunction; // 哈希函数对象

public:
    // 插入字符串元素到布隆过滤器中
    void insert(const std::string& str) {
        // 计算三次哈希值
        size_t hash1 = hashFunction(str);
        size_t hash2 = hashFunction(str + "salt"); // 添加盐增加哈希种子的多样性
        size_t hash3 = hashFunction(str + "pepper");

        // 将对应位数组位置设置为1
        bitArray[hash1 % bitArray.size()] = 1;
        bitArray[hash2 % bitArray.size()] = 1;
        bitArray[hash3 % bitArray.size()] = 1;
    }

    // 检查布隆过滤器中是否包含字符串元素
    bool contains(const std::string& str) {
        // 计算三次哈希值
        size_t hash1 = hashFunction(str);
        size_t hash2 = hashFunction(str + "salt");
        size_t hash3 = hashFunction(str + "pepper");

        // 检查对应位数组位置是否都为1
        return bitArray[hash1 % bitArray.size()] &&
               bitArray[hash2 % bitArray.size()] &&
               bitArray[hash3 % bitArray.size()];
    }
};

int main() {
    BloomFilter filter;

    // 插入一些示例字符串
    filter.insert("apple");
    filter.insert("banana");
    filter.insert("cherry");

    // 检查某些字符串是否存在于布隆过滤器中
    std::cout << "Contains apple: " << filter.contains("apple") << std::endl; // 应该返回1 (true)
    std::cout << "Contains grape: " << filter.contains("grape") << std::endl; // 应该返回0 (false)

    return 0;
}


优缺点

优点

  1. 空间效率高:相比其他数据结构(如哈希表),布隆过滤器使用位数组来存储数据,因此空间占用非常小。
  2. 查询速度快:布隆过滤器的查询操作只涉及到位运算和哈希计算,因此查询速度非常快,接近O(1)时间复杂度。
  3. 灵活性高:布隆过滤器可以动态地添加元素,而不需要像传统数据结构那样进行扩容或重新哈希。

缺点

  1. 误报率:布隆过滤器存在误报的可能性。当查询一个不存在的元素时,由于哈希冲突的存在,布隆过滤器可能会错误地认为该元素存在于集合中。误报率可以通过调整位数组大小和哈希函数数量来控制,但无法完全消除。
  2. 不支持删除操作:布隆过滤器不支持从集合中删除元素。一旦一个元素被插入到布隆过滤器中,就无法直接删除它。这是因为删除操作可能会影响到其他元素的判断结果。
  3. 哈希函数的选择:哈希函数的选择对布隆过滤器的性能有很大影响。如果哈希函数设计不好,可能会导致误报率过高。因此,在选择哈希函数时需要考虑其均匀性和独立性等特性。

应用场景

布隆过滤器在许多场景下都有广泛的应用,包括但不限于:

  1. 缓存穿透:在缓存系统中,布隆过滤器可以用来判断请求的数据是否存在于缓存中,从而避免直接穿透到数据库层。
  2. 垃圾邮件过滤:布隆过滤器可以用来过滤已知的垃圾邮件地址或内容,减少不必要的邮件处理开销。
  3. Web爬虫:在Web爬虫中,布隆过滤器可以用来记录已经爬取过的URL,避免重复爬取。
  4. 推荐系统:在推荐系统中,布隆过滤器可以用来快速判断用户是否对某个物品感兴趣(基于历史行为数据),从而快速生成推荐列表。

面试常问

问题1:什么是布隆过滤器?

解答:布隆过滤器是一个空间效率极高的概率型数据结构,它利用位数组和哈希函数来判断一个元素是否可能存在于一个集合中。布隆过滤器可以快速地告诉你某个元素很可能不存在于集合中(没有误报),或者某个元素可能存在(有误报)。

问题2:布隆过滤器如何处理误报?

解答:布隆过滤器存在误报的可能性,即它可能会错误地认为某个元素存在于集合中。这是由于哈希冲突和位数组的空间限制导致的。然而,布隆过滤器不会漏报,即它永远不会错误地告诉你某个元素不存在于集合中。如果布隆过滤器返回可能存在,那么你需要使用其他方法(如数据库查询)来确认该元素是否真的存在。

问题3:如何设计布隆过滤器以最小化误报率?

解答:要最小化布隆过滤器的误报率,你可以考虑以下方法:

  1. 增加位数组的大小:位数组越大,误报率越低。但是,这也会增加布隆过滤器的存储空间和计算成本。
  2. 增加哈希函数的数量:使用更多的哈希函数可以进一步降低误报率。但是,这也会增加计算复杂性和时间成本。
  3. 选择合适的哈希函数:哈希函数的选择对布隆过滤器的性能有很大影响。你应该选择那些均匀分布且独立的哈希函数。

问题4:布隆过滤器有哪些应用场景?

解答:布隆过滤器在许多场景下都有广泛的应用,包括但不限于:

  1. 缓存穿透:在缓存系统中,布隆过滤器可以用来判断请求的数据是否存在于缓存中,从而避免直接穿透到数据库层。
  2. 垃圾邮件过滤:布隆过滤器可以用来过滤已知的垃圾邮件地址或内容,减少不必要的邮件处理开销。
  3. Web爬虫:在Web爬虫中,布隆过滤器可以用来记录已经爬取过的URL,避免重复爬取。
  4. 推荐系统:在推荐系统中,布隆过滤器可以用来快速判断用户是否对某个物品感兴趣(基于历史行为数据),从而快速生成推荐列表。

问题5:布隆过滤器与哈希表有什么区别?

解答:布隆过滤器和哈希表在数据结构上有很大的区别。哈希表是一种确定性的数据结构,它使用哈希函数将键映射到桶中,并存储相应的值。哈希表可以准确地告诉你一个键是否存在(没有误报和漏报)。然而,哈希表需要为每个键存储值,因此其空间效率相对较低。布隆过滤器则是一种概率型数据结构,它只使用位数组和哈希函数来判断元素是否存在。布隆过滤器可以快速地告诉你一个元素很可能不存在(没有误报),但可能会误报。由于布隆过滤器不需要存储值,因此其空间效率非常高。

问题6:布隆过滤器在插入元素后,其准确性主要体现在哪些方面?

  1. 正确拒绝(False Negative):如果一个元素从未被添加到布隆过滤器中,并且布隆过滤器正确地判断它不存在,那么这是一个正确的结果(没有误报)。布隆过滤器永远不会错误地报告一个从未被添加的元素存在,即它不会产生假阴性(False Negative)。

  2. 误报(False Positive):然而,布隆过滤器的一个主要限制是可能会产生误报(False Positive)。这意味着布隆过滤器可能会错误地报告一个实际上并未被添加的元素存在。这是由于哈希冲突和位数组的空间限制导致的。当两个或多个不同的元素在多个哈希函数的作用下映射到位数组的相同位置时,这些位置上的位都会被设置为1。因此,当查询一个从未被添加的元素时,如果这些位置上的位都是1,布隆过滤器就会错误地认为该元素存在。

布隆过滤器的误报率取决于几个因素,包括位数组的大小、哈希函数的数量以及添加到过滤器中的元素数量。位数组越大,哈希函数数量越多,误报率就越低。但是,这也会增加布隆过滤器的存储空间和计算成本。因此,在设计布隆过滤器时,需要根据具体的应用场景和需求来权衡这些因素。

需要注意的是,虽然布隆过滤器可能会产生误报,但它通常用于那些可以容忍一定误报率的场景。例如,在缓存穿透、垃圾邮件过滤和Web爬虫等应用中,即使布隆过滤器偶尔会产生误报,也不会对整体应用产生太大的影响。在这些场景中,布隆过滤器的优点(如空间效率高、查询速度快)往往超过了其可能产生的误报率所带来的缺点。

问题7:布隆过滤器的原理是什么?

解答: 布隆过滤器基于位数组和哈希函数。当一个元素被加入到布隆过滤器中时,通过多个哈希函数对该元素进行哈希计算,得到多个哈希值,然后将对应的位数组位置设为1。当需要判断一个元素是否存在于布隆过滤器中时,同样通过多个哈希函数计算该元素的哈希值,并检查对应的位数组位置是否都为1。如果所有位置都为1,则说明该元素可能存在于集合中;如果存在任意一个位置不为1,则说明该元素一定不在集合中。

问题8:布隆过滤器如何处理哈希碰撞?

解答: 布隆过滤器使用多个哈希函数来减少碰撞的可能性。如果发生了哈希碰撞,即两个不同的元素被映射到了相同的位数组位置,那么在检查元素是否存在时,如果有任意一个哈希位置不为1,则该元素被判断为不存在于集合中。

问题9:在什么情况下不适合使用布隆过滤器?

解答: 布隆过滤器适用于需要快速判断一个元素是否属于一个集合的场景,但它不适用于需要精确判断元素是否存在的场景,因为存在一定的误判率。此外,由于布隆过滤器需要消耗额外的空间来存储位数组和哈希函数,因此在内存资源受限的情况下,不适合使用布隆过滤器。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1716855.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

智能仓储物流系统(WMS)系列-货品与分类管理

好的应用系统应是细分简单&#xff0c;界面简洁易操作&#xff0c;程序代码简洁易懂的。

和隋永珍 大麗和和珠宝美学特展闪耀巴黎

2024年5月21日&#xff0c;“和隋永珍”大麗和和珠宝美学特展在巴黎优雅启幕。二零二四甲辰龙年&#xff0c;恰逢中法两国建交60周年&#xff0c;大麗和和以现代东方高级珠宝为引&#xff0c;探讨中国美学的传承与创新&#xff0c;共襄东西方文化交流之盛举。 高级珠宝品牌大麗…

设计模式21——命令模式

写文章的初心主要是用来帮助自己快速的回忆这个模式该怎么用&#xff0c;主要是下面的UML图可以起到大作用&#xff0c;在你学习过一遍以后可能会遗忘&#xff0c;忘记了不要紧&#xff0c;只要看一眼UML图就能想起来了。同时也请大家多多指教。 命令模式&#xff08;Command&…

mysql连接不上可能的原因:防火墙放行mysql的3306端口 全库复制:data目录替换即可 mysql查看版本

1.看本地localhost能否连接 2.在本地看IP能否连接 能说明本地正常 权限也够 都能的话&#xff0c;ip能否ping通 能就说明可能是防火墙原因了。关闭防火墙及杀毒试试。 我这里关防火墙就能访问了。 windows如何开启防火墙&#xff0c;又放行mysql的3306端口&#xff1f; 在 …

盘点韩语中的四字成语柯桥留学韩语学习外语培训

일석이조 一石二鸟 일거양득 一举两得 호장성세 虚张声势 새옹15857575376#지마 塞翁失马 간담상조 肝胆相照 이심전심 心心相印 동고동락 同甘共苦 외유내강 外柔内刚 입신양명 扬名立万 다다익선 多多益善 거두절미 截头去尾 일사천리 一泻千里 자유자재 自由自在 탁상공

操作系统总结6

目录 3.2.1 虚拟内存的基本概念 &#xff08;1&#xff09;知识总览 ​编辑&#xff08;2&#xff09;传统管理方式的特征、缺点 &#xff08;3&#xff09;局部性原理 &#xff08;4&#xff09;虚拟内存的定义和特征 &#xff08;5&#xff09;如何实现虚拟内存技术 总…

IO系列(九) -什么是零拷贝

一、摘要 相信不少的网友&#xff0c;在很多的博客文章里面&#xff0c;已经见到过零拷贝这个词&#xff0c;会不禁的发出一些疑问&#xff0c;什么是零拷贝&#xff1f; 从字面上我们很容易理解出&#xff0c;零拷贝包含两个意思&#xff1a; 拷贝&#xff1a;就是指数据从…

记录贴 Elasticsearch的RestClient进行DSL查询

must&#xff1a;必须匹配每个子查询&#xff0c;类似“与” should&#xff1a;选择性匹配子查询&#xff0c;类似“或” must_not&#xff1a;必须不匹配&#xff0c;不参与算分&#xff0c;类似“非” filter&#xff1a;必须匹配&#xff0c;不参与算分 import cn.huto…

nginx+keepalived实现nginx高可用集群

实现nginx的高可用 一、简要介绍 ​ nginx作为一款企业级的代理服务器&#xff0c;在各种企业事业单位中&#xff0c;均有广泛的使用&#xff0c;尤其是在前后端分离的项目中&#xff0c;nginx作为路由转发的功能是非常常用的。在一些流量比较大的项目中&#xff0c;为了应对…

idea+tomcat+mysql 从零开始部署Javaweb项目(保姆级别)

文章目录 新建一个项目添加web支持配置tomcat优化tomcat的部署运行tomcatidea数据库连接java连接数据库 新建一个项目 new project&#xff1b;Java&#xff1b;选择jdk的版本&#xff1b;next&#xff1b;next&#xff1b;填写项目名字&#xff0c;选择保存的路径&#xff1b;…

raid 磁盘阵列

raid 磁盘阵列&#xff1a; **条带化存储&#xff1a;**数据分散在多个物理磁盘上的存储方式。利用多个磁盘并行读取和写入。 条带化的存储性能和读写性能是最好的。 磁盘的组成方式不同&#xff0c;也就是不同的raid级别&#xff1a; **raid 0&#xff08;条带化存储&#x…

.net JQ AJAX 请求 FromBody 接收格式

$.ajax({ url: “/api/banchang/EmpTble/Login2”, type: ‘Post’, data: JSON.stringify({ Emppassword: pass, EmpName: name }), contentType: ‘application/json’, beforeSend: function () { // 禁用按钮防止重复提交 /* $(“#create”).attr({ disabled: “disabled”…

SpringBoot与Spring Framework提供的缓存抽象

目录 缓存 项目总结 新建一个SpringBoot项目 pom.xml application.properties CacheConfig Book BookRepository接口 BookService服务类 BookController控制器 SpringbootCacheApplication启动类 启动项目&#xff0c;使用Postman测试 参考博文&#xff1a; 1、使用…

短视频脚本创作的五个方法 沈阳短视频剪辑培训

说起脚本&#xff0c;我们大概都听过影视剧脚本、剧本&#xff0c;偶尔可能在某些综艺节目里听过台本。其中剧本是影视剧拍摄的大纲&#xff0c;用来指导影视剧剧情的走向和发展&#xff0c;而台本则是综艺节目流程走向的指导大纲。 那么&#xff0c;短视频脚本是什么&#xf…

服务器端请求伪造--SSRF

SSRF 简介 ##SSRF定义 SSRF(Server-Side Request Forgery:服务器端请求伪造)是一种由 攻击者构造形成&#xff0c;由服务端发起请求 的一个安全漏洞。一般情况下&#xff0c;SSRF攻击的目标是从 外网无法访问的内部系统&#xff08;正是因为它是由服务端发起的&#xff0c;所…

FineReport帆软设计器,远程连接服务器

FineReport报表工具一款纯Java编写的企业级web报表软件工具。它能够全面支持主流的B/S架构以及传统的C/S架构&#xff0c;部署方式简单而灵活. 需要使用FineReport帆软设计器&#xff0c;配置远程服务器的方式如下&#xff1a; 1、打开帆软设计器&#xff0c;点击文件&#x…

工程项目管理系统的Java实现:高效协同与信息共享

在当今的工程领域&#xff0c;项目管理的高效协同和信息共享是提升工作效率、降低成本的关键。本文将向您介绍一款基于Java技术构建的工程项目管理系统&#xff0c;该系统采用前后端分离的先进技术框架&#xff0c;功能全面&#xff0c;能够满足不同角色的需求&#xff0c;从项…

中英文语音合成芯片(TTS芯片)WT3000T8-在ETC上的应用案例

一&#xff1a;开发背景&#xff1a; 随着智能化浪潮的推进&#xff0c;ETC&#xff08;电子不停车收费&#xff09;系统已逐渐成为现代交通的重要组成部分。在这一背景下&#xff0c;唯创知音自主研发的WT3000T8中文转语音合成芯片&#xff08;TTS芯片&#xff09;以其卓越的性…

基于TAE的数字钥匙自动化测试解决方案

方案概述 在汽车发展和用户需求的推动下&#xff0c;汽车钥匙开始从传统的机械钥匙向数字化、智能化方向发展。目前常见的数字钥匙集成了蓝牙、NFC、UWB等技术实现了移动设备与车端的通信&#xff0c;可以帮助用户便捷的实现车辆功能控制。随着数字钥匙的广泛应用&#xff0c;相…

振弦式位移计在各类工程中的应用

振弦式位移计&#xff0c;作为一种高精度、高可靠性的测量工具&#xff0c;在各类工程中发挥着至关重要的作用。它通过测量弦的振动频率来间接得出结构的位移变化&#xff0c;为工程师和科学家们提供了精确的数据支持&#xff0c;从而确保工程的安全性和稳定性。 点击输入图片描…