[C++]哈希应用-布隆过滤器快速入门

news2025/1/11 21:58:40

布隆过滤器

布隆过滤器(Bloom Filter)是一个由布隆在1970年提出的概率型数据结构,它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器的主要特点是高效的插入和查询,可以用于检索一个元素是否在一个集合中。

原理:

  • 布隆过滤器是采用位图的方式来记录数据的存在与否
  • 将要存储的数据同时映射到位图的多个节点上
  • 当寻找数据时,只需将要找的数据进行映射,观察全部映射节点的情况,就可以判断数据存在与否

其核心功能如下(此处以数据库使用布隆过滤器为例):

在这里插入图片描述

解释:

对于一个数据的查找,会先去布隆过滤器中进行多个映射点的查询。会有如下情况发生:

  1. 只有当每个映射点都存在(对应位置为1)的时候,才能说明该数据可能存在,下一步就去Database中进一步确认(因为冲突的原因,所以可能某个数据的每个映射点虽然都为1,但是该数据并不存在其中)。
  2. 如果有任何一个映射点不存在(对应位置为0)的时候,就说明该数据并不在存储空间内。

如何选择映射

布隆的核心就是最大限度减少冲突问题,进而在高查找效率的情况下,减少寻找错误的可能性!

现在提出一个问题:如果我只采用一个映射(每个数据只映射到一个位图节点上),由于哈希的局限性以及开辟空间的有限性,就会出现多个数据映射到同一个位置上

所以布隆过滤器就采用了多映射的方案(即一个值映射到多个位图节点上),大大缩小了冲突的可能性

优点:

  1. 多于不同的数据,他们在某个哈希函数下可能映射到了同一个位置,但是对于多个映射全相同的概率极小,这就使得哈希冲突变小
  2. 由于数据的查询一般采用轮询的方式(或者树形结构)导致时间复杂度较大,而布隆过滤器的查询效率是大O(1)(忽略极个别的全冲突情况)

缺点:

  1. 不存在漏报,但存在误报(即对于数据存在的判断有失准确性)。但严格来说该缺点不算大事
  2. 不能在布隆过滤器中删除元素,因为这会影响到别的与该位图节点有关联的数据(但可以改造他,使他可以实现删除操作)

哈希函数的选择:

可以采用BKDRAP等哈希函数

选择的哈希函数的前提是:需要保证映射后的值能合理放到位图中的对应位置上(如果你映射出来一个:164gxap3,那么你该放入位图中的哪个位置呢?是吧)

应用场景

  1. 快速检索元素:布隆过滤器能够快速地检索一个元素是否在一个集合中,而无需访问整个集合。这大大提高了查询效率,尤其是在处理大数据集时。
  2. 网页URL去重:在搜索引擎或爬虫系统中,布隆过滤器可以用于过滤已经访问过的网页URL,避免重复访问和存储。
  3. 垃圾邮件过滤:布隆过滤器可以存储已知的垃圾邮件发送者的地址或特征,当接收到新邮件时,可以通过检查邮件地址或内容是否在布隆过滤器中来判断其是否为垃圾邮件。
  4. 数据库查询优化:在数据库中,布隆过滤器可以用于减少不必要的磁盘查找操作。例如,当查询一个不存在的行或列时,布隆过滤器可以快速判断该数据是否存在于数据库中,从而避免不必要的磁盘访问。
  5. 恶意代码检测:在网络安全领域,布隆过滤器可以用于检测恶意代码的僵尸网络或分析不断变化的市场数据。通过存储已知的恶意代码特征或行为模式,布隆过滤器可以快速判断新发现的代码是否为恶意代码。
  6. 生物信息学应用:布隆过滤器可以用于快速查找DNA测序数据中的基因序列,以及在其他生物学和遗传学领域如蛋白质组学、转录组学和基因组学等进行数据分析。
  7. 非结构化大数据分析:在企业数据分析中,布隆过滤器可以帮助企业快速检测网站中的指定元素(如URL中的关键字、用户搜索的关键字等),从而找出其中的趋势和模式,帮助企业更好地投资和发展。
  8. 机器学习应用:在机器学习领域,布隆过滤器可以用于快速处理海量数据,提取特征并构建模型。由于布隆过滤器的快速查询能力,它可以大大提高模型训练和预测的效率。

代码实现以及成果演示

存储的元素:“hello”, “world”, “你好”, “no thank”, “why”, “4”, “-78”

查找的元素:“world”,“你好”,“早上好”,“no thank”,“8”,“4”,“0”,“-78”

分别采用了BKDR、AP、DJB三个哈希函数

uint64_t BKDR_Hash(const char* str) {
    uint64_t seed = 131; // 31 131 1313 13131 131313 etc..  
    uint64_t hash = 0;

    while (*str) {
        hash = hash * seed + (*str++);
    }

    return hash;
}
uint64_t AP_Hash(const char* str)
{
    uint64_t hash = 0;
    int i;

    for (i = 0; *str; i++)
    {
        if ((i & 1) == 0)
        {
            hash ^= ((hash << 7) ^ (*str++) ^ (hash >> 3));
        }
        else
        {
            hash ^= (~((hash << 11) ^ (*str++) ^ (hash >> 5)));
        }
    }

    return (hash & 0x7FFFFFFF);
}
uint64_t DJB_Hash(const char* str)
{
    uint64_t hash = 5381;

    while (*str)
    {
        hash += (hash << 5) + (*str++);
    }

    return (hash & 0x7FFFFFFF);
}
int main()
{
    bitset<10000> st;
    vector<string> vstr{"hello", "world", "你好", "no thank", "why", "4", "-78"};

    for (int i = 0; i < vstr.size(); i++)
    {
        st.set(BKDR_Hash(vstr[i].c_str()) % st.size());
        st.set(AP_Hash(vstr[i].c_str()) % st.size());
        st.set(DJB_Hash(vstr[i].c_str()) % st.size());
    }
    vector<string> vfind{"world","你好","早上好","no thank","8","4","0","-78"};
    for (int i = 0; i < vfind.size(); i++)
    {
        cout << vfind[i];
        if (st[BKDR_Hash(vfind[i].c_str()) % st.size()]
            && st[AP_Hash(vfind[i].c_str()) % st.size()]
            && st[DJB_Hash(vfind[i].c_str()) % st.size()])
        {
            cout << " exist" << endl;
        }
        else
        {
            cout << " not exixt" << endl;
        }
    }
	return 0;
}

查找结果:

world exist
你好 exist
早上好 not exixt
no thank exist
8 not exixt
4 exist
0 not exixt
-78 exist

优化成可实现删除操作

对于前面的布隆过滤器的写法,有一个很明显的问题:对于数据的删除是不可实现的,因为对任意一个数据映射位置的删除,由于哈希冲突,都可能导致影响到别的数据的映射关系

所以我们采用引用计数+扩展位图的方式来实现删除操作,具体操作如下:

采用引用计数的方案,对每一个哈希映射值都采用引用计数。每新增一个映射关系就++,减少一个映射关系就- -

如此一来,对位图也需要有所更改:增大位图空间开销,比如用8个bit表示一个映射关系,而在这8个bit中就可以用引用计数实现0-255的可映射数量

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

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

相关文章

射频无源器件之耦合器

一. 耦合器的作用 在射频电路中,射频耦合器将一路微波功率按比例分成几路,用于检测或监测信号,如功率测量和波检测,还可改变信号的幅度、相位等特性,以满足不同的通信需求。根据输入与耦合端的功率差,常被分为5dB、6dB、10dB等耦合器。射频耦合器的类型主要包括定向耦合…

Infuse for Mac激活版:高清影音播放软件

对于热爱影音娱乐的Mac用户来说&#xff0c;Infuse for Mac是一个不容错过的选择。它以其简洁的操作界面和强大的播放功能&#xff0c;为用户带来了全新的影音播放体验。 Infuse for Mac支持广泛的音视频格式&#xff0c;无需额外转换&#xff0c;即可轻松播放您喜爱的影片。无…

2024年教育创新与人文艺术国际学术会议(ICEIHA 2024)

2024年教育创新与人文艺术国际学术会议(ICEIHA 2024) 2024 International Conference on Educational Innovation and Humanities and Arts 一、【会议简介】 2024年教育创新与人文艺术国际学术会议&#xff0c;将探讨教育创新与人文艺术的结合。 本次会议将汇集全球的专家学者…

使用idea管理docker

写在前面 其实idea也提供了docker的管理功能&#xff0c;比如查看容器列表&#xff0c;启动容器&#xff0c;停止容器等&#xff0c;本文来看下如何管理本地的docker daemon和远程的dockers daemon。 1&#xff1a;管理本地 双击shift&#xff0c;录入service&#xff1a; …

【3dmax笔记】026:挤出和壳修改器的使用

文章目录 一、修改器二、挤出三、壳 一、修改器 3ds Max中的修改器是一种强大的工具&#xff0c;用于创建和修改复杂的几何形状。这些修改器可以改变对象的形状、大小、方向和位置&#xff0c;以生成所需的效果。以下是一些常见的3ds Max修改器及其功能&#xff1a; 挤出修改…

C++学习————第十天(string的基本使用)

1、string 对象类的常见构造 (constructor)函数名称 功能说明&#xff1a; string() &#xff08;重点&#xff09; 构造空的string类对象&#xff0c;即空字符串 string(const char* s) &#xff08;重点&#xff09;…

二层交换机与防火墙连通上网实验

防火墙是一种网络安全设备&#xff0c;用于监控和控制网络流量。它可以帮助防止未经授权的访问&#xff0c;保护网络免受攻击和恶意软件感染。防火墙可以根据预定义的规则过滤流量&#xff0c;例如允许或阻止特定IP地址或端口的流量。它也可以检测和阻止恶意软件、病毒和其他威…

【linux软件基础知识】-死锁问题

死锁问题 当两个或多个线程由于每个线程都在等待另一个线程持有的资源而无法继续时,就会发生死锁 如下图所示, 在线程 1 中,代码持有了 L1 上的锁,然后尝试获取 L2 上的锁。 在线程 2 中,代码持有了 L2 上的锁,然后尝试获取 L1 上的锁。 在这种情况下,线程 1 已获取 L…

这个簇状柱形图怎么添加百分比?

这个图表是excel默认的图表配色&#xff0c;有的人做出来都那个百分比&#xff0c;一起来做一个这样的图表。 1.插入图表 选中数据区域&#xff0c;点击 插入选项卡&#xff0c;在图表那一栏&#xff0c;点一下柱形图右侧那个倒三角&#xff0c;在弹邮对话框中&#xff0c;选…

vivado刷题笔记46

题目&#xff1a; Design a 1-12 counter with the following inputs and outputs: Reset Synchronous active-high reset that forces the counter to 1 Enable Set high for the counter to run Clk Positive edge-triggered clock input Q[3:0] The output of the counter c…

26_Scala集合常用API汇总

文章目录 1.mkString2.size&#xff0c;length&#xff0c;isEmpty,contains3.reverse ,length,distinct4.获取数据相关4.1数据准备4.2准确获取尾部last4.3 除了最后一个元素不要其他都要4.4从集合获取部分数据 5.删除数据5.1删除3个从左边5.2删除3个右边 6.切分数据splitAt(n:…

Windows下启动Tomcat显示乱码解决办法

1、Windows下启动Tomcat显示乱码 2、解决办法 找到 D:\apache-tomcat-9.0.89\conf下的logging.properties&#xff0c;找到java.util.logging.ConsoleHandler.encoding的值改为GBK&#xff0c;就可以了 完美解决&#xff01;显示正常的中文了

Ansible——playbook编写

一、简介 1.什么是playbook Ansible Playbook 是设定自动化任务的一种蓝图&#xff0c;可在无需人工干预或有限干预的前提下执行复杂的 IT 操作。Ansible Playbook 对一组或一类共同构成 Ansible 清单的主机执行。 Ansible Playbook 本质上是一些框架&#xff0c;是一些预先编…

指定地区|CSC高级研究学者赴澳大利亚访学交流

CSC高级研究学者均是正高或博导级的&#xff0c;学术背景较强&#xff0c;多数能DIY联系到国外合作机构。但也有些申请者因指定地域或学校&#xff0c;或须在短期内获取邀请函故而求助于我们。本案例D教授就指定澳大利亚的墨尔本地区&#xff0c;我们最终用维多利亚大学的邀请函…

企业是保留传统的MES还是换新的MES?

在选择上MES系统的时候&#xff0c;企业可以根据自身所处行业不同、当前阶段不同&#xff0c;以及业务需求的差异&#xff0c;对症下药&#xff0c;选择适合自己的解决方案。对于有些企业本来就有MES系统&#xff0c;但是已经过时过旧&#xff0c;就要考虑换新的MES系统了. 保留…

射频无源器件之巴伦

一. 巴伦的作用 Balun,balanced-unbalanced的缩写,即平衡-不平衡转换器,是一种三端口无源器件,其本质是通过电感线圈的相互耦合实现的信号转换。用于平衡信号(差分信号,即振幅相等、相位相差180 的两个信号)与非平衡信号(单端信号)的相互转换。 Balun是高频电路重要器…

深入探索 C++ 中 string 的用法:从基础到实践

C String 用法详解 C中的 std::string 是一个非常强大且灵活的类&#xff0c;用于处理字符串。std::string 类是C标准库中的一部分&#xff0c;它提供了丰富的成员函数来执行各种字符串操作&#xff0c;如连接、比较、查找、替换等。在本篇博客中&#xff0c;我们将深入探索 s…

uniapp实现下拉刷新效果-uniapp原生接口

onPullDownRefresh | uni-app官网 1、需要在 pages.json 里&#xff0c;找到的当前页面的pages节点&#xff0c;并在 style 选项中开启 enablePullDownRefresh 2、生命周期中添加onPullDownRefresh&#xff0c;下拉时获取数据 3、处理完数据后&#xff0c;停止下拉效果stopPul…

嵌入式开发适不适合做鸿蒙南向开发?看完这篇你就了解了~

随着物联网和智能设备的快速发展&#xff0c;嵌入式开发和鸿蒙系统成为了当前技术领域的热门话题。鸿蒙系统作为华为推出的全场景分布式操作系统&#xff0c;旨在连接各种智能设备&#xff0c;提供无缝的跨设备体验。而南向开发则是鸿蒙系统中的一个重要方向&#xff0c;主要涉…

数据结构复习/学习9--堆/堆实现/升降序建堆/top-k问题

一、堆与完全二叉树 1.堆的逻辑与物理结构 2.父节点与子节点的下标 3.大小根堆 二、堆的实现&#xff08;大根堆为例&#xff09; 注意事项总结&#xff1a; 注意堆中插入与删除数据的位置和方法与维持大根堆有序时的数据上下调整 三、堆排序(基于上述的向上与向下调整建堆)…