哈希重要思想续——布隆过滤器

2024-06-03 20:52

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

布隆过滤器

  • 一 概念
    • 1.1布隆过滤器的提出
    • 2.概念
  • 二 模拟实现
    • 2.1 三个仿函数
    • set
    • Test
  • 全代码
  • 三 实际应用

一 概念

1.1布隆过滤器的提出

我们在使用新闻客户端看新闻时,它会给我们不停地推荐新的内容,它每次推荐时要去重,去掉那些已经看过的内容。问题来了,新闻客户端推荐系统如何实现推送去重的? 用服务器记录了用户看过的所有历史记录,当推荐系统推荐新闻时会从每个用户的历史记录里进行筛选,过滤掉那些已经存在的记录。 如何快速查找呢?

  1. 用哈希表存储用户记录,缺点:浪费空间
  2. 用位图存储用户记录,缺点:位图一般只能处理整形,如果内容编号是字符串就无法处理了。
  3. 将哈希与位图结合,即布隆过滤器

就像是我们在逛淘宝的时候,如此多的信息是如何被处理的?这就是我们要学习的布隆过滤器。

在这里插入图片描述

2.概念

布隆过滤器是由布隆(Burton Howard Bloom)在1970年提出的 一种紧凑型的、比较巧妙的概率型数据结构,特点是高效地插入和查询,可以用来告诉你 “某样东西一定不存在或者可能存在”,它是用多个哈希函数,将一个数据映射到位图结构中。此种方式不仅可以提升查询效率,也可以节省大量的内存空间。

我们用图来解释这个概念。
在这里插入图片描述
用位图的方式(整型代替字符串),一个字符串对应一个,但是如图出现了冲突
我们对这个冲突进行一下讨论,

  • 对于在的值:可能会有误判
  • 对于不在的值:这个就是准确的

看来一个值映射一个位置无法做到识别。所以布隆过滤器就是一个值映射多个位置如图
在这里插入图片描述
可以看到一个值去映射多个位置可以大大降低冲突的概率,这也应征了概念的话 ” 某样东西一定不存在或者可能存在 “

二 模拟实现

上面说了布隆过滤器的精髓就在于一个值映射多个位置我们的模拟实现用映射三个位置来实现。

2.1 三个仿函数

struct Hashfunc1
{size_t operator()(const string& s){size_t hash = 0;for (auto i : s){hash += i;}return hash;}
};
struct Hashfunc2
{size_t operator()(const string& s){size_t hash = 0;for (size_t i = 0; i < s.size(); i++){if ((i & 1) == 0) // 偶数位字符{hash ^= ((hash << 7) ^ (s[i]) ^ (hash >> 3));}else              // 奇数位字符{hash ^= (~((hash << 11) ^ (s[i]) ^ (hash >> 5)));}}return hash;}
};
struct Hashfunc3
{size_t operator()(const string& s){size_t hash = 5381;for (auto ch : s){hash = hash * 33 ^ ch;}return hash;}
};

这些我们都可以去网站上随便挑选几个写入即可各种字符串的Hash函数

对于布隆过滤器中他的大小要设置成多少,这也是个数学问题,可以参考此文章
布隆过滤器长度
我这里就把他设置成5;

set

	void Set(const K& key){size_t hash1 = Hash1()(key) % M;size_t hash2 = Hash2()(key) % M;size_t hash3 = Hash3()(key) % M;_bs->set(hash1);_bs->set(hash2);_bs->set(hash3);}

Test

	bool Test(const K& key){size_t hash1 = Hash1()(key) % M;if (_bs->test(hash1) == false){return false;}size_t hash2 = Hash2()(key) % M;if (_bs->test(hash2) == false){return false;}size_t hash3 = Hash3()(key) % M;if (_bs->test(hash3) == false){return false;}return true;}

全代码

struct Hashfunc1
{size_t operator()(const string& s){size_t hash = 0;for (auto i : s){hash += i;}return hash;}
};
struct Hashfunc2
{size_t operator()(const string& s){size_t hash = 0;for (size_t i = 0; i < s.size(); i++){if ((i & 1) == 0) // 偶数位字符{hash ^= ((hash << 7) ^ (s[i]) ^ (hash >> 3));}else              // 奇数位字符{hash ^= (~((hash << 11) ^ (s[i]) ^ (hash >> 5)));}}return hash;}
};
struct Hashfunc3
{size_t operator()(const string& s){size_t hash = 5381;for (auto ch : s){hash = hash * 33 ^ ch;}return hash;}
};
template<size_t N, class K = string, class Hash1 = Hashfunc1,class Hash1 = Hashfunc2, class Hash1 = Hashfunc3>
class BloomFilter
{void Set(const K& key){size_t hash1 = Hash1()(key) % M;size_t hash2 = Hash2()(key) % M;size_t hash3 = Hash3()(key) % M;_bs->set(hash1);_bs->set(hash2);_bs->set(hash3);}bool Test(const K& key){size_t hash1 = Hash1()(key) % M;if (_bs->test(hash1) == false){return false;}size_t hash2 = Hash2()(key) % M;if (_bs->test(hash2) == false){return false;}size_t hash3 = Hash3()(key) % M;if (_bs->test(hash3) == false){return false;}return true;}
private:static const size_t M = 5 * N;bitset<M> _bs;
};

注意,布隆过滤器不好做删除操作,当删除一个数之后,别的数出现误判的可能性会增大。

三 实际应用

给两个文件,分别有100亿个query,我们只有1G内存,如何找到两个文件交集?分别给出精确算法
假设一个query有50个字节,100亿个query占500g的内存。这时候就用到了哈希切分
在这里插入图片描述
相同query,一定会进入编号相同的文件中。再把Ai和Bi的query分别放入set中,再在这个set中找交集。

这篇关于哈希重要思想续——布隆过滤器的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

深度解析Spring Boot拦截器Interceptor与过滤器Filter的区别与实战指南

《深度解析SpringBoot拦截器Interceptor与过滤器Filter的区别与实战指南》本文深度解析SpringBoot中拦截器与过滤器的区别,涵盖执行顺序、依赖关系、异常处理等核心差异,并... 目录Spring Boot拦截器(Interceptor)与过滤器(Filter)深度解析:区别、实现

spring-gateway filters添加自定义过滤器实现流程分析(可插拔)

《spring-gatewayfilters添加自定义过滤器实现流程分析(可插拔)》:本文主要介绍spring-gatewayfilters添加自定义过滤器实现流程分析(可插拔),本文通过实例图... 目录需求背景需求拆解设计流程及作用域逻辑处理代码逻辑需求背景公司要求,通过公司网络代理访问的请求需要做请

Java如何将文件内容转换为MD5哈希值

《Java如何将文件内容转换为MD5哈希值》:本文主要介绍Java如何将文件内容转换为MD5哈希值的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Java文件内容转换为MD5哈希值一个完整的Java示例代码代码解释注意事项总结Java文件内容转换为MD5

Spring Boot拦截器Interceptor与过滤器Filter深度解析(区别、实现与实战指南)

《SpringBoot拦截器Interceptor与过滤器Filter深度解析(区别、实现与实战指南)》:本文主要介绍SpringBoot拦截器Interceptor与过滤器Filter深度解析... 目录Spring Boot拦截器(Interceptor)与过滤器(Filter)深度解析:区别、实现与实

9个SpringBoot中的自带实用过滤器使用详解

《9个SpringBoot中的自带实用过滤器使用详解》在SpringBoot应用中,过滤器(Filter)是处理HTTP请求和响应的重要组件,SpringBoot自带了许多实用的过滤器,如字符编码,跨... 目录1. CharacterEncodingFilter - 字符编码过滤器功能和配置手动配置示例2

SpringBoot整合jasypt实现重要数据加密

《SpringBoot整合jasypt实现重要数据加密》Jasypt是一个专注于简化Java加密操作的开源工具,:本文主要介绍详细介绍了如何使用jasypt实现重要数据加密,感兴趣的小伙伴可... 目录jasypt简介 jasypt的优点SpringBoot使用jasypt创建mapper接口配置文件加密

Spring Boot拦截器Interceptor与过滤器Filter详细教程(示例详解)

《SpringBoot拦截器Interceptor与过滤器Filter详细教程(示例详解)》本文详细介绍了SpringBoot中的拦截器(Interceptor)和过滤器(Filter),包括它们的... 目录Spring Boot拦截器(Interceptor)与过滤器(Filter)详细教程1. 概述1

dubbo3 filter(过滤器)如何自定义过滤器

《dubbo3filter(过滤器)如何自定义过滤器》dubbo3filter(过滤器)类似于javaweb中的filter和springmvc中的intercaptor,用于在请求发送前或到达前进... 目录dubbo3 filter(过滤器)简介dubbo 过滤器运行时机自定义 filter第一种 @A

Java 8 Stream filter流式过滤器详解

《Java8Streamfilter流式过滤器详解》本文介绍了Java8的StreamAPI中的filter方法,展示了如何使用lambda表达式根据条件过滤流式数据,通过实际代码示例,展示了f... 目录引言 一.Java 8 Stream 的过滤器(filter)二.Java 8 的 filter、fi

Linux Mint Xia 22.1重磅发布: 重要更新一览

《LinuxMintXia22.1重磅发布:重要更新一览》Beta版LinuxMint“Xia”22.1发布,新版本基于Ubuntu24.04,内核版本为Linux6.8,这... linux Mint 22.1「Xia」正式发布啦!这次更新带来了诸多优化和改进,进一步巩固了 Mint 在 Linux 桌面