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

布隆过滤器

  • 一 概念
    • 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中找交集。

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

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

相关文章

Java面试八股之守护线程和普通线程的区别

守护线程和普通线程的区别 生命周期差异&#xff1a; 普通线程&#xff08;也称为用户线程&#xff09;&#xff1a;这类线程的生命周期与程序的生命周期独立。它们会一直运行直到完成自己的任务或主动结束&#xff0c;如果一个程序中只剩下普通线程在运行&#xff0c;即使主…

JavaScript、Kotlin、Flutter可以开发鸿蒙APP吗?

自从去年华为宣布推出「鸿蒙Next」版本开始&#xff0c;标志着其操作系统的全面革新。鸿蒙Next将摒弃所有基于AOSP的代码&#xff0c;与Android系统彻底分离&#xff0c;实现完全自主的研发路径。通过精简约40%的冗余代码&#xff0c;鸿蒙Next致力于构建一个更高效、更流畅的系…

混合动力电动汽车介绍(二)

接续前一章内容&#xff0c;本篇文章介绍混合动力汽车串联、并联和混联的系统组成和工作原理。 一、串联混合动力电动汽车的系统组成和工作原理 上图为串联混合动力电动汽车的结构简图。汽车由电动机-发电机驱动行驶&#xff0c;电机控制器的动力来自油箱-发动机-发电机-发电机…

Python画图(多图展示在一个平面)

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

上位机图像处理和嵌入式模块部署(f407 mcu vs f103)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 对于一部分嵌入式场景来说&#xff0c;f103其实已经足够了&#xff0c;特别是要求不高的低速场合。如果开发的代码比较多&#xff0c;还可以选用更…

Java面试八股之线程池中submit和execute方法的区别

线程池中submit和execute方法的区别 接口和返回值类型: execute()方法属于Executor接口&#xff0c;它接收一个实现了Runnable接口的任务&#xff0c;并不返回任何结果。它的主要目的是异步执行任务&#xff0c;不关心任务的执行结果。 submit()方法则是ExecutorService接口…

Vue渲染函数与JSX指南

title: Vue渲染函数与JSX指南 date: 2024/6/3 下午6:43:53 updated: 2024/6/3 下午6:43:53 categories: 前端开发 tags:Vue渲染JSX基础性能优化组件对比React JSX大项目测试策略 第1章&#xff1a;Vue.js入门 Vue.js的历史和背景 Vue.js是一个用于构建用户界面的JavaScript框…

模拟堆-java

模拟堆也是对堆的一次深入理解和一些其它操作&#xff0c;可以了解一下。 文章目录 前言 一、模拟堆 二、算法思路 1.结点上移 2.结点下移 3.插入一个数 4.输出当前集合的最小值 5.删除当前集合的最小值&#xff08;数据保证此时的最小值唯一&#xff09; 6.删除第k个插入的数 …

初识STM32单片机-ADC和DMA

初识STM32单片机-ADC和DMA 一、ADC(模拟数字转换器)简介二、ADC基本结构三、DMA(直接存储器读取)简介四、DMA框图和基本结构五、DMA应用实例5.1 数据转运DMA5.2 ADC扫描DMA 六、程序编码6.1 ADC单通道-电位器6.2 ADC多通道-电位器和光敏\热敏\反射红外传感器6.3 DMA数据转运6.4…

代码随想录算法训练Day28|LeetCode93-复原IP地址、LeetCode78-子集问题、LeetCode90-子集2

复原IP地址 题目描述 力扣93-复原IP地址 有效 IP 地址 正好由四个整数&#xff08;每个整数位于 0 到 255 之间组成&#xff0c;且不能含有前导 0&#xff09;&#xff0c;整数之间用 . 分隔。 例如&#xff1a;"0.1.2.201" 和 "192.168.1.1" 是 有效 …

贝锐花生壳DDNS:远程访问数据库,仅需简单3步

在当今数字化时代&#xff0c;数据的远程访问和管理变得至关重要。无论是企业还是个人开发者&#xff0c;都需要一种简单、安全的方式来远程访问和管理本地部署的数据库&#xff0c;如MySQL、PostgreSQL、MongoDB等。贝锐花生壳DDNS服务提供了一个完美的解决方案&#xff0c;通…

【YOLOv10改进[Backbone]】图像修复网络AirNet助力YOLOv10目标检测效果 + 含全部代码和详细修改方式 + 手撕结构图 + 全网首发

本文带来的是图像复原网络AirNet&#xff0c;它由基于对比度的退化编码器( CBDE )和退化引导的恢复网络( DGRN )两个模块组成。可以在一个网络中恢复各种退化图像。AirNet不受损坏类型和级别的先验限制&#xff0c;仅使用观察到的损坏图像进行推理。本文中将使用图像修复网络Ai…

SCARA机器人中旋转花键的维护和保养方法!

作为精密传动元件的一种&#xff0c;旋转花键在工作过程中承受了较大的负荷。在自动化设备上运用广泛&#xff0c;如&#xff1a;水平多关节机械手臂&#xff08;SCARA&#xff09;、产业用机器人、自动装载机、雷射加工机、搬运装置、机械加工中心的ATC装置等&#xff0c;最适…

R语言安装caret包报错

R语言安装caret包报错&#xff1a;Error: package or namespace load failed for ‘caret’ in loadNamespace(i, c(lib.loc, .libPaths()), versionCheck vI[[i]]): 不存在叫‘recipes’这个名字的程辑包 https://rbasics.org/packages/caret-package-in-r/ R版本的问题&…

什么牌子的洗地机清洁效果强?618热门品牌推荐与详解

近年来&#xff0c;洗地机的销量急剧增长&#xff0c;已成为清洁类家电中销量第二大的产品。其更新迭代速度也非常快&#xff0c;功能和技术层出不穷&#xff0c;许多消费者不知道如何选择合适的型号。为了帮助大家以最少的花费买到清洁力强的洗地机&#xff0c;笔者特意总结了…

输入法不显示选字框

期望效果&#xff1a; 当前效果&#xff1a; 啥也没干突然就这样了 原因&#xff1a;需要以兼容性运行微软输入法 一、进入输入法设置 右键输入法小图标 选择设置 二、进入常规设置 三、开启兼容性运行 完&#xff01;

跨越百亿营收的今世缘,全国化进程仍挑战重重?

当前&#xff0c;白酒市场正在经历一场深度调整&#xff0c;随着存量时代到来&#xff0c;白酒品牌地位的更替和竞争格局的重构已经展开。这一背景下&#xff0c;今世缘等地方性酒企也正在凭借对区域市场的深耕&#xff0c;展现出较快的成长速度&#xff0c;并希望能借此占领市…

【JAVA |总结】JAVASE基础大总结(含思维导图)

✨✨谢谢大家捧场&#xff0c;祝屏幕前的小伙伴们每天都有好运相伴左右&#xff0c;一定要天天开心哦&#xff01;✨✨ &#x1f388;&#x1f388;作者主页&#xff1a; &#x1f388;丠丠64-CSDN博客&#x1f388; ✨✨ 帅哥美女们&#xff0c;我们共同加油&#xff01;一起…

数据动态变化时实现多选及回显

<template><el-dialog title"设置权限" :visible.sync"showDialog" :close-on-click-modal"false" :append-to-body"true" width"800px"><div v-loading"loading"><el-radio-group v-model&…

TDMQ CKafka 版弹性存储能力重磅上线!

导语 自 2024年5月起&#xff0c;TDMQ CKafka 专业版支持弹性存储能力&#xff0c;这种产品形态下&#xff0c;存储可按需使用、按量付费&#xff0c;一方面降低消费即删除、存储使用波动大场景下的存储成本&#xff0c;另一方面存储空间理论上无穷大。 TDMQ CKafka 版产品能…