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

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:在什么情况下不适合使用布隆过滤器?

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Cobaltstrike框架介绍

Cobaltstrike简介 cobalt strike&#xff08;简称CS&#xff09;是一款团队作战渗透测试神器&#xff0c;分为客户端及服务端&#xff0c;一个服务端可以对应多个客户 端&#xff0c;一个客户端可以连接多个服务端&#xff0c;可被团队进行分布式协团操作. 和MSF关系 metas…

Java使用apache.poi生成word

加油&#xff0c;打工人&#xff01; 工作需求&#xff0c;将现有的word模板有段落和表格&#xff0c;从数据库中查出数据并填充&#xff0c;word里面也有表格数据&#xff0c;需要将excel表格数据单独处理&#xff0c;然后插入到生成好的word文档中。 下面代码模拟从数据库查出…

【简单易用,新人友好】一个轻量级生物信息学流程框架,从此解决99%的生物信息学流程搭建问题...

生物信息学数据分析流程的搭建是一项繁重而复杂的工作。随着行业的发展&#xff0c;各种生信流程框架层出不穷&#xff0c;比如有: NextflowSnakemakeCWLWDL 各种标准&#xff0c;各种规则&#xff0c;令人眼花缭乱。选择太多&#xff0c;往往令人无所适从。特别是新进入行业的…

SwiftUI中的Stepper(系统Stepper以及自定义Stepper)

本篇文章主要介绍一下Stepper&#xff0c;这个组件在UIKit中也已经有较长的历史了&#xff0c;下面看看在SwiftUI中如何使用&#xff0c;有哪些更加便捷的方法呢&#xff1f; Stepper减号(-)和加号()按钮&#xff0c;可以点击后以指定的数值进行加减。 基础初始化方法 Stepp…

NDIS驱动开发-NET_BUFFER体系

网络数据由通过网络发送或接收的数据包组成。 NDIS 提供数据结构来描述和组织此类数据。 NDIS 6.0 及更高版本的主要网络数据结构包括&#xff1a; NET_BUFFERNET_BUFFER LISTNET_BUFFER_LIST_CONTEXT 它们之间的关系如下: 在 NDIS 6.0 及更高版本中&#xff0c; NET_BUFFER …

基于python数据挖掘在淘宝评价方面的应用与分析,技术包括kmeans聚类及情感分析、LDA主题分析

随着电子商务的蓬勃发展&#xff0c;淘宝作为中国最大的在线购物平台之一&#xff0c;吸引了大量的消费者进行购物并留下了大量的客户评价。这些客户评价中包含了丰富的消费者意见和情感信息&#xff0c;对于商家改进产品、提升服务质量以及消费者决策都具有重要的参考价值。 …

一个机器学习问题的重新定义

任何事物都有两面性。 一些机器学习问题也是如此。并非每个回归问题&#xff08;你认为的&#xff09;都需要回归。仔细考虑和审视问题的业务不仅可以帮助开发更好的模型&#xff0c;还可以找到有效的解决方案。 重构或重新定义&#xff08;reframing&#xff09;是一种改变机…

数据结构-思考完全二叉树

我们知道在完全二叉树中 &#xff1a; &#xff08;孩子下标-1&#xff09;/ 2 父节点下标 父节点下标*21 左孩子节点 父节点下标*22 右孩子节点 那我们该怎样理解以便之后不容易忘记呢&#xff1f; 以下是我的思考过程&#xff1a;观察下边的完全二叉树的下标规律…

Docker HTTPS api V2 Manifest V 2, Schema 2 下的免装docker下载镜像的方法

目录 前言 下载镜像代码 使用方法 原代码中无法适配 Schema 2 的原因浅析 如何解决 相对原代码改动的东西 前言 本文提供代码主要是基于 https://github.com/NotGlop/docker-drag 提供的代码修改的。链接中提供的代码应该是是基于HTTPS api V2 Manifest V 2, Schema 1实…

如何使用pycrypt加密工具测试反病毒产品的检测性能

关于pycrypt pycrypt是一款基于Python 3语言开发的加密工具&#xff0c;广大研究人员可以使用该工具来尝试绕过任意类型的反病毒产品&#xff0c;以检测目标反病毒产品的安全性能。 功能介绍 1、目前已知反病毒产品检测率为0/40&#xff1b; 2、支持绕过任意EDR解决方案&#…

Nodejs+Socket.io+Web端完成聊天

前言 源码获取:nodeexpresssocket.ioweb: 聊天demo (gitee.com) 目录结构 后端依赖 启动方式 前端是html正常启动 后端是node app.js 后端app.js核心代码 const express require(express) const app express() var http require(http).Server(app) var io require(so…

AI网络爬虫-自动获取百度实时热搜榜

工作任务和目标&#xff1a;自动获取百度实时热搜榜的标题和热搜指数 标题&#xff1a;<div class"c-single-text-ellipsis"> 东部战区台岛战巡演练模拟动画 <!--48--></div> <div class"hot-index_1Bl1a"> 4946724 </div> …

uniapp+vue3+ts开发小程序或者app架构时候的UI框架选型

使用vue3tsviteuniapp开发小程序或者跨平台app的趋势越来越高&#xff0c;有一个顺手的UI的框架还是非常重要的&#xff0c;官方维护的 uni-ui&#xff0c;支持全端&#xff0c;而且有类型提示&#xff0c;目前已经内置到 GitHub - Sjj1024/uniapp-vue3: 使用uniapp和vue3 ts …

01-05.Vue自定义过滤器

目录 前言过滤器的概念过滤器的基本使用给过滤器添加多个参数 前言 我们接着上一篇文章01-04.Vue的使用示例&#xff1a;列表功能 来讲。 下一篇文章 02-Vue实例的生命周期函数 过滤器的概念 概念&#xff1a;Vue.js 允许我们自定义过滤器&#xff0c;可被用作一些常见的文本…

Photoshop插件(UXP)编写过程中,如何更新sp-checkbox的选中状态

✨问题说明 sp-checkbox是uxpSpectrum UXP Widgets下的一个小组件&#xff0c;内置样式大概是这样&#xff1a; 那么&#xff0c;如果用js动态的改变选中的状态&#xff0c;应该如何做呢&#xff1f; 如果直接是html来写&#xff1a; <sp-checkbox checked>Checked<…

部门来了个测试开发,听说是00后,上来一顿操作给我看蒙了...

公司新来了个同事&#xff0c;听说大学是学的广告专业&#xff0c;因为喜欢IT行业就找了个培训班&#xff0c;后来在一家小公司实习半年&#xff0c;现在跳槽来我们公司。来了之后把现有项目的性能优化了一遍&#xff0c;服务器缩减一半&#xff0c;性能反而提升4倍&#xff01…

Java——图书管理系统万字详解(附代码)

框架搭建 book包 将书相关的放到book包中&#xff0c;创建一个Book类用来设置书的属性&#xff0c;包括书名、作者、价格、类型、是否被借出等。 以上属性均被private所修饰 利用编译器生成构造方法&#xff08;不需要构造isBorrowed&#xff0c;因为其初始值为false&#…

代码审计--一道简单的文件包含题目的多种利用方式

NO.1 传统方法 首先来看下代码 <?php error_reporting(0); if(isset($_GET["file"])){include($_GET["file"]); }else{highlight_file(__FILE__);phpinfo(); } ?>看完代码后再来学习学习函数吧&#xff0c;毕竟菜啊&#xff01;&#xff01;&…

【图书推荐】《Vue.js 3.x+Element Plus从入门到精通(视频教学版)》

配套示例源码与PPT课件下载 百度网盘链接: https://pan.baidu.com/s/1nBQLd9UugetofFKE57BE5g?pwdqm9f 自学能力强的&#xff0c;估计不要书就能看代码学会吧。 内容简介 本书通过对Vue.js&#xff08;简称Vue&#xff09;的示例和综合案例的介绍与演练&#xff0c;使读者…

【独家揭秘!玩转ChatGPT?一文带你解锁秘籍!】

&#x1f680;【独家揭秘&#xff01;玩转ChatGPT&#xff1f;一文带你解锁秘籍&#xff01;】&#x1f680; &#x1f449; 【直达ChatGPT体验站】 ChatGPT&#xff0c;全称“Chat Generative Pre-trained Transformer”&#xff0c;是人工智能研究实验室OpenAI于2022年底推出…