哈希应用之布隆过滤器及其实现

2024-05-03 23:28

本文主要是介绍哈希应用之布隆过滤器及其实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • 布隆过滤器
      • 模拟实现

布隆过滤器

我们在上一篇中主要说的是位图,是用于判断整形是否存在的一种应用,但是他不好的地方就是只能判断整形了,如果是字符串的话就难再应用了

在之前哈希表中,我们使用了一些哈希函数来将字符串转化成整形,再存入哈希表

这里我们是否可以使用同样的方法呢

其实我们讲,可以但是还不够,因为相似的字符串很容易就会产生哈希冲突,本质上来说还是因为字符串的数量太庞大,远远超出了整形能承受的范围,从而形成一种多对少的效果,产生了冲突

那么对于这样的冲突,也不能直接存字符串,因为使用位图本身就是为了节省空间的

这时候就有人想到了一个方法,既然一个关键字(哈希地址)容易产生冲突,那么我如果使用两种不同的哈希函数,每一个字符串对应两个哈希地址,只有当两个哈希地址都是1的时候,我们才认为该字符串是已经存在的

但是这种存在依旧是“不可靠”的,在数据量特别巨大的时候,可能是别的字符串,恰好占用了这两个地址,此时就会误判,但是判断不存在的时候就是可靠的了,因为只要有一个是0,就说明这个字符串并不存在

这也就是为什么我们称之为过滤器,简单说一种应用就是用户注册时不允许重复名称,当我们查询时,发现不存在,这时就不需要再额外消耗资源去数据库中进行对比了,直接就可以确认,而当布隆过滤器发现,他是有可能存在的时候,再到数据库中对比,如果真的存在,再说不允许重复名称即可,这样就能节省大量的服务器资源,还能提高查询效率

模拟实现

struct BKDRHash {size_t operator()(const string& key) {size_t hash = 0;for (auto e : key) {hash *= 32;hash += e;}return hash;}
};struct APHash {size_t operator()(const string& key) {size_t hash = 0;for (auto e : key) {if ((e & 1) == 0) {hash ^= (hash << 7) ^ e ^ (hash >> 3);}else {hash ^= (~(hash << 11) ^ e ^ (hash >> 5));}}return hash;}
};struct DJBHash {size_t operator()(const string& key) {size_t hash = 0;for (auto e : key) {hash += (hash << 5) + e;}return hash;}
};template<size_t N, class K= string
, class HashFunc1=BKDRHash
, class HashFunc2=APHash
, class HashFunc3=DJBHash>
class BloomFilter {
public:void Set(const K& key) {size_t hash1 = HashFunc1()(key) % N;size_t hash2 = HashFunc2()(key) % N;size_t hash3 = HashFunc3()(key) % N;_bs.set(hash1);_bs.set(hash2);_bs.set(hash3);}bool Test(const K& key) {size_t hash1 = HashFunc1()(key) % N;if (_bs.test(hash1) == false)return false;size_t hash2 = HashFunc2()(key) % N;if (_bs.test(hash2) == false)return false; size_t hash3 = HashFunc3()(key) % N;if (_bs.test(hash3) == false)return false;// 可能误判的存在return true;}
private:bitset<N> _bs;
};

布隆过滤器一般是不支持删除的,因为一个删除需要同时删除几个位置的值,有可能会影响其他位置的元素

当然我们也可以想别的办法支持,例如将每个比特位作为计数器,插入元素时就加一,删除元素时减一

但是这种操作会让存储量成倍增加,而且也无法确认元素是否真正在过滤器中

这篇关于哈希应用之布隆过滤器及其实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/957880

相关文章

使用zip4j实现Java中的ZIP文件加密压缩的操作方法

《使用zip4j实现Java中的ZIP文件加密压缩的操作方法》本文介绍如何通过Maven集成zip4j1.3.2库创建带密码保护的ZIP文件,涵盖依赖配置、代码示例及加密原理,确保数据安全性,感兴趣的... 目录1. zip4j库介绍和版本1.1 zip4j库概述1.2 zip4j的版本演变1.3 zip4

python生成随机唯一id的几种实现方法

《python生成随机唯一id的几种实现方法》在Python中生成随机唯一ID有多种方法,根据不同的需求场景可以选择最适合的方案,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习... 目录方法 1:使用 UUID 模块(推荐)方法 2:使用 Secrets 模块(安全敏感场景)方法

Redis中Stream详解及应用小结

《Redis中Stream详解及应用小结》RedisStreams是Redis5.0引入的新功能,提供了一种类似于传统消息队列的机制,但具有更高的灵活性和可扩展性,本文给大家介绍Redis中Strea... 目录1. Redis Stream 概述2. Redis Stream 的基本操作2.1. XADD

Spring StateMachine实现状态机使用示例详解

《SpringStateMachine实现状态机使用示例详解》本文介绍SpringStateMachine实现状态机的步骤,包括依赖导入、枚举定义、状态转移规则配置、上下文管理及服务调用示例,重点解... 目录什么是状态机使用示例什么是状态机状态机是计算机科学中的​​核心建模工具​​,用于描述对象在其生命

Spring Boot 结合 WxJava 实现文章上传微信公众号草稿箱与群发

《SpringBoot结合WxJava实现文章上传微信公众号草稿箱与群发》本文将详细介绍如何使用SpringBoot框架结合WxJava开发工具包,实现文章上传到微信公众号草稿箱以及群发功能,... 目录一、项目环境准备1.1 开发环境1.2 微信公众号准备二、Spring Boot 项目搭建2.1 创建

IntelliJ IDEA2025创建SpringBoot项目的实现步骤

《IntelliJIDEA2025创建SpringBoot项目的实现步骤》本文主要介绍了IntelliJIDEA2025创建SpringBoot项目的实现步骤,文中通过示例代码介绍的非常详细,对大家... 目录一、创建 Spring Boot 项目1. 新建项目2. 基础配置3. 选择依赖4. 生成项目5.

JSONArray在Java中的应用操作实例

《JSONArray在Java中的应用操作实例》JSONArray是org.json库用于处理JSON数组的类,可将Java对象(Map/List)转换为JSON格式,提供增删改查等操作,适用于前后端... 目录1. jsONArray定义与功能1.1 JSONArray概念阐释1.1.1 什么是JSONA

nginx -t、nginx -s stop 和 nginx -s reload 命令的详细解析(结合应用场景)

《nginx-t、nginx-sstop和nginx-sreload命令的详细解析(结合应用场景)》本文解析Nginx的-t、-sstop、-sreload命令,分别用于配置语法检... 以下是关于 nginx -t、nginx -s stop 和 nginx -s reload 命令的详细解析,结合实际应

Linux下删除乱码文件和目录的实现方式

《Linux下删除乱码文件和目录的实现方式》:本文主要介绍Linux下删除乱码文件和目录的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux下删除乱码文件和目录方法1方法2总结Linux下删除乱码文件和目录方法1使用ls -i命令找到文件或目录

SpringBoot+EasyExcel实现自定义复杂样式导入导出

《SpringBoot+EasyExcel实现自定义复杂样式导入导出》这篇文章主要为大家详细介绍了SpringBoot如何结果EasyExcel实现自定义复杂样式导入导出功能,文中的示例代码讲解详细,... 目录安装处理自定义导出复杂场景1、列不固定,动态列2、动态下拉3、自定义锁定行/列,添加密码4、合并