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

布隆过滤器

  • 一 概念
    • 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.mzph.cn/news/847042.shtml

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

相关文章

【数学】填不同的自然数 1/9=1/()+1/()+1/()+1/()+1/()

填不同的自然数 1 9 1 ( ) 1 ( ) 1 ( ) 1 ( ) 1 ( ) \frac{1}{9}\frac{1}{(\text{ })}\frac{1}{(\text{ })}\frac{1}{(\text{ })}\frac{1}{(\text{ })}\frac{1}{(\text{ })} 91​( )1​( )1​( )1​( )1​( )1​ 推理&#xff1a; 1 1 − 1 2 1 2 − 1 3 1 3 … − 1…

springboot管理的各依赖版本查看

找一个springboot相关的依赖&#xff0c;比如这里我找mybatis 鼠标点击artifactId名称&#xff0c;图中蓝色字段&#xff0c;跳转到springboot依赖&#xff08;鼠标悬停在上面变成蓝色表示可点击跳转&#xff09;&#xff0c; 点击spring-boot-dependencites&#xff0c;跳转到…

python用tanh画图

用tanh函数画图 圆形 import numpy as np import matplotlib.pyplot as plt# 创建一个二维网格 xx np.linspace(-1, 1, 1000) yy np.linspace(-1, 1, 1000) x_i, y_i np.meshgrid(xx, yy)# 圆的半径和中心 r 0.4 center_x, center_y 0, 0 # 假设圆心在(0, 0)# 计算每个网…

pandas添加行

方法1(df.append()) import pandas as pd# 创建一个空的DataFrame df pd.DataFrame(columns[Column1, Column2])# 新增一行数据 data {Column1: Value1, Column2: Value2} df df.append(data, ignore_indexTrue) print(df)raw_data {"Column1":"adafafa&quo…

探究JSON和XML:两种常见的数据交换格式之异同

在软件开发和数据交换领域&#xff0c;JSON&#xff08;JavaScript Object Notation&#xff09;和XML&#xff08;eXtensible Markup Language&#xff09;是两种广泛使用的数据交换格式。它们都具有将数据结构化并在不同系统之间进行传输和解析的能力&#xff0c;但在实际应用…

详解redis配置文件

华子目录 基础配置查看配置文件位置启动redis时&#xff0c;指定加载的配置文件示例 include引用其他配置文件units单位大小写不敏感network网络配置bind配置方式示例 protected-mode功能概述默认值配置方法安全建议总结 porttcp-backlog1. 定义2. 默认值3. 优化建议4. 注意事项…

OpenEuler 的安装过程记录

一、下载openEuler镜像 1.2 打开官网&#xff0c;选择openEuler23.09 1.3 选择架构、场景以及软件包类型 初次使用的话基本上都是先安装虚拟机&#xff0c;我们大部分主机都是x86_64架构&#xff0c;场景的话就选服务器&#xff0c;软件版类型选择标准版&#xff0c;可以安装图…

【稳定检索/投稿优惠】2024年环境、资源与区域经济发展国际会议(ERRED 2024)

2024 International Conference on Environment, Resources and Regional Economic Development 2024年环境、资源与区域经济发展国际会议 【会议信息】 会议简称&#xff1a;ERRED 2024 大会地点&#xff1a;中国杭州 会议官网&#xff1a;www.icerred.com 会议邮箱&#xff1…

电子邮件注入

电子邮件注入 1.电子邮件注入概述2.在发送的电子邮件中注入3.绕过邮件网关白名单检查4.硬退信率DOS攻击 1.电子邮件注入概述 电子邮件注入是一种电子邮件安全漏洞&#xff0c;攻击者通过在输入字段中注入特殊字符或命令来操纵电子邮件的内容。这通常发生在电子邮件表单或应用程…

python中编码与解码简记

python中编码与解码简记 一、读取文本文件指定的编码方式二、字符串与字节格式互转三、Base64编码解码3.1Base64 编解码使用的参数类型3.2Base64 编码后的字符串显示3.3Base64 解码后的字符串显示 四、Quoted-Printable编码解码4.1Quoted-Printable编解码使用的参数类型4.2Quot…

基本元器件 - 二极管

目录 二极管的主要参数 二极管的分类 整流二极管 快恢复二极管&#xff08;FRD&#xff09; 稳压&#xff08;齐纳&#xff09;二级管 瞬态电压抑制器&#xff08;TVS&#xff09; 开关二极管 肖特基二极管&#xff08;SBD&#xff09; 正偏与反偏 常用封装 伏安特性…

Android中focusableInTouchMode会导致第一次点击事件失效

我们很多时候会对某些View设置点击事件&#xff0c;但是&#xff0c;当对这个View同时设置了focusableInTouchModetrue时&#xff0c;第一次点击事件会被消费为为此View获取焦点。 <Viewandroid:id"id/v_click"android:layout_width"match_parent"andr…

第二篇 多路数据选择器

实验二 多路数据选择器 2.1 实验目的 理解多路数据选择器的概念&#xff1b; 使用门级结构描述实现多路选择器&#xff1b; 使用行为描述实现多路选择器&#xff1b; 完成实验设计、仿真&#xff0c;并在DE1-SOC上验证电路。 2.2 原理介绍 在多路数据传送过程中&#xf…

238.除以自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积。 题目数据保证数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂度内完…

Gson解析会丢失默认属性值

问题&#xff1a;类的属性中有设置默认值&#xff0c;Gson中如果不包含该属性时&#xff0c;应该会使用该默认值。如下&#xff1a; class MyPointBean {inner class InnerBean {var altitude 0.0var gradually 1} }val gson GsonBuilder().create()val pStr ""…

linux网络端口

[roottest2 data7]# ifconfig ens33: flags4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 #enss33&#xff1a;设备名称 up 启动 该设备支持广播&#xff0c;正在运行&#xff0c;支持组播 最大传输单元。inet 192.168.60.20 netmask 255.255.255.0 broadca…

Mac连接U盘后怎么读取 Mac连接U盘后怎么取消只读模式

在使用Mac电脑时&#xff0c;连接U盘是一项常见的需求。无论是传输文件还是备份数据&#xff0c;正确地读取U盘对于Mac用户至关重要。然而&#xff0c;当连接的U盘格式为NTFS时&#xff0c;在Mac中进行数据编辑会遇到一些困难。下面我们来看看Mac连接U盘后怎么读取&#xff0c;…

进程线程(一.2)

进程与线程&#xff08;一&#xff09; 并发编程并发与并行高并发 进程特征什么是进程&#xff1f;线程&#xff1f;进程与程序的区别进程与线程区别进程的五状态进程的种类 查看进程命令ps auxps axjpstreekill 进程的创建fork函数fork总结vfork函数fork与vfork区别 获取进程I…

传输协议TCP-原理部分

传输控制协议TCP&#xff08;Transmission Control Protocol&#xff09;一种基于连接的可靠的稳定的无重复的传输协议。 1、TCP头部信息 TCP协议头部信息如下&#xff1a; 一共占用20个字节 16位源端口号&#xff1a;发送进程的主机端口16位目的端口号&#xff1a;接收主机…

实现Dropdown下拉菜单监听键盘上下键选中功能-React

用过ant design的小伙伴都知道&#xff0c;select组件是支持联想搜索跟上下键选中的效果的&#xff0c;但是在项目中我们可能会遇到用select组件无法实现我们的需求的情况&#xff0c;比如说一个div框&#xff0c;里面有input&#xff0c;又有tag标签&#xff0c;在input中输入…