C++布隆过滤器

news2025/1/16 6:02:55

目录

  • 布隆过滤器
    • 介绍
    • 实现
      • 哈希函数
      • 布隆过滤器
      • 删除
    • 小结
    • 使用——题目

布隆过滤器

介绍

在许多场景下,如设置昵称时,往往要求唯一性。这时就需要高效判断该昵称是否被使用过。

  • 使用红黑树的kv模型或者哈希表来组织昵称集合,可以,但缺点是可能使用浪费大量内存空间

  • 使用位图,将字符串先转换为整型数字,然后映射到具体比特位上,通过0/1状态判断。可以,但缺点是发生哈希冲突,导致不同昵称最终映射到相同的比特位,发生误判。


布隆过滤器

    可以用来告诉你 “某样东西一定不存在或者可能存在”。它是用多个哈希函数,将一个数据映射到位图结构中。提升查询效率,节省大量的内存空间

  • 将一个数据通过多个哈希函数映射到多个比特位。
  • 查询某个数据是否存在时,通过这些哈希函数映射到对应比特位。如果都为1,则存在;如果有一位为0,则不存在。
  • 使用多个不同的哈希函数,可以降低误判率
    (如:某个未被使用的昵称,经过多个哈希函数映射后,还是有可能和昵称集合中某些映射到相同比特位,发现全为1,误判:该昵称已经被使用)

在这里插入图片描述

随着1的比特位逐渐增多,误判率也会增加,存在(可以忍受的)错误率,通过调整哈希函数和位图大小来平衡。


如何选择合适的k和m值呢?
k为哈希函数个数,m为布隆过滤器长度,n为插入的元素个数,p为误判率

这里有一个公式:

m = − n l n p ( l n 2 ) 2 k = m n l n 2 m=-\frac{nlnp}{(ln2)^2}\\ k=\frac{m}{n}ln2 m=(ln2)2nlnpk=nmln2

当哈希函数个数 k = 3 k=3 k=3 l n 2 ≈ 0.7 ln2\approx0.7 ln20.7,则 m = 4.3 n m=4.3n m=4.3n,即位图长度应该是插入元素个数的4~5倍

实现

哈希函数

下面三个都是比较经典的字符串转整型的哈希函数

struct HashBKDR
{
	// BKDR
	size_t operator()(const string& key)
	{
		size_t val = 0;
		for (auto ch : key)
		{
			val *= 131;
			val += ch;
		}

		return val;
	}
};

struct HashAP
{
	// BKDR
	size_t operator()(const string& key)
	{
		size_t hash = 0;
		for (size_t i = 0; i < key.size(); i++)
		{
			if ((i & 1) == 0)
			{
				hash ^= ((hash << 7) ^ key[i] ^ (hash >> 3));
			}
			else
			{
				hash ^= (~((hash << 11) ^ key[i] ^ (hash >> 5)));
			}
		}
		return hash;
	}
};
struct HashDJB
{
	// BKDR
	size_t operator()(const string& key)
	{
		size_t hash = 5381;
		for (auto ch : key)
		{
			hash += (hash << 5) + ch;
		}

		return hash;
	}
};

布隆过滤器

// N表示准备要映射N个值
template<size_t N,
	class K = string, class Hash1 = HashBKDR, class Hash2 = HashAP, class Hash3 = HashDJB>
	class BloomFilter
{
public:
	void Set(const K& key)
	{
		size_t hash1 = Hash1()(key) % (_ratio * N);
		_bits->set(hash1);

		size_t hash2 = Hash2()(key) % (_ratio * N);
		_bits->set(hash2);

		size_t hash3 = Hash3()(key) % (_ratio * N);
		_bits->set(hash3);
	}

	bool Test(const K& key)
	{
		size_t hash1 = Hash1()(key) % (_ratio * N);
		if (!_bits->test(hash1))
			return false; // 准确的

		size_t hash2 = Hash2()(key) % (_ratio * N);
		if (!_bits->test(hash2))
			return false; // 准确的

		size_t hash3 = Hash3()(key) % (_ratio * N);
		if (!_bits->test(hash3))
			return false;  // 准确的

		return true; // 可能存在误判
	}

	// 不支持删除
	//void Reset(const K& key);

private:
    //开辟_ration * 5个比特位空间,减少误判率
	const static size_t _ratio = 5;
	std::bitset<_ratio * N>* _bits = new std::bitset<_ratio * N>;
};

删除

布隆过滤器不能直接支持删除工作,因为在删除一个元素时,可能会影响其他元素。(如:删除某个昵称后,将其映射的几个比特位为0,可能会导致其他已使用的昵称被判定为未使用)
在这里插入图片描述

小结

优点:不存储元素本身,节约空间,保密,增加和查询效率高

缺点:存在误判

对于已保存在布隆过滤器中的元素,test()不会出现误判;对于未保存的,可能会误判,认为已存在。

使用——题目

除了可以应用在设置昵称。也可以在设置黑名单,阻止非法访问。

1.给两个文件,分别有100亿个query,我们只有1G内存,如何找到两个文件交集?分别给出精确算法和近似算法

近似算法:允许一些误判。将一个文件的所有query(字符串)映射进一个布隆过滤器中,然后使用另一个文件对布隆过滤器进行test(),如果在,就是交集部分。

精确算法:不允许误判。哈希切分,假设每个query占30byte,100亿query需要300亿byte,约300G。内存不能加载那么大的空间,则需要先切分成小块。
在这里插入图片描述

2.如何扩展BloomFilter使得它支持删除元素的操作

用多个位表示一个位置,做计数。但是为了支持删除,空间消耗更多,优势削弱了


    🦀🦀观看~~

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

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

相关文章

Qt中的日期和时间

目录 QDate 示例&#xff08;打印年月日&#xff09;&#xff1a; QTime 示例&#xff08;显示时分秒&#xff09;&#xff1a; QDateTime 示例&#xff08;显示当前日期和时间&#xff09;&#xff1a; 示例&#xff08;分别取出 年 月 日 时 分 秒&#xff09;&#xff…

牛客网专项练习——C语言错题集(8)

文章目录 字符串拼接和拷贝while 与 fortypedef 和 define浮点类型的组成部分 字符串拼接和拷贝 这题并没有难度&#xff0c;但不知为什么我把该题空着。 strcpy 用于拷贝字符串&#xff0c;strcat 用于拼接字符串。 while 与 for 假如 i 0&#xff0c;while 循环里 s1 被执…

【AI机器学习入门与实战】机器学习算法都有哪些分类?

&#x1f44d;【AI机器学习入门与实战】目录 &#x1f36d;基础篇 &#x1f525; 第一篇&#xff1a;【AI机器学习入门与实战】AI 人工智能介绍 &#x1f525; 第二篇&#xff1a;【AI机器学习入门与实战】机器学习核心概念理解 &#x1f525; 第三篇&#xff1a;【AI机器学习入…

Z变换方程转化为差分方程

将Z变换方程转换为差分方程的过程称为反Z变换。反Z变换是将信号从复频域转换为时间域的过程。如果我们已知一个系统的传递函数&#xff0c;即Z变换方程&#xff1a; H ( z ) Y ( z ) X ( z ) b n b n − 1 z − 1 ⋯ b 0 z − n 1 a n a n − 1 z − 1 ⋯ a 0 z − n 0…

AVL 树

目录 AVL树的概念AVL树节点的定义AVL树的插入AVL树的旋转左单旋(parent->_bf 2 && cur->_bf 1)a,b,c当高度为0a,b,c当高度为1a,b,c当高度为2a,b,c当高度为...... 右单旋(parent->_bf -2 && cur->_bf -1)a,b,c当高度为0a,b,c当高度为1a,b,c当高…

强化学习从基础到进阶-案例与实践[4]:深度Q网络-DQN、double DQN、经验回放、rainbow、分布式DQN

【强化学习原理项目专栏】必看系列&#xff1a;单智能体、多智能体算法原理项目实战、相关技巧&#xff08;调参、画图等、趣味项目实现、学术应用项目实现 专栏详细介绍&#xff1a;【强化学习原理项目专栏】必看系列&#xff1a;单智能体、多智能体算法原理项目实战、相关技巧…

Azkaban初认识

Azkaban初认识 文章目录 Azkaban初认识Azkaban是什么&#xff1f;为什么需要工作流调度系统&#xff1f;常见的工作流调度系统Azkaban 与 Oozie的对比 Azkaban是什么&#xff1f; Azkaban是一个开源的分布式工作流管理器&#xff0c;在LinkedIn实施&#xff0c;以解决Hadoop作业…

RT-Thread-03-栈空间分配

栈空间分配 线程状态转换图&#xff1a; 系统滴答时钟 每个操作系统都存在一个系统时钟&#xff0c;是操作系统中最小的时钟单位。这个时钟负责系统和时间相关的一些操作。这个时钟由硬件定时器的定时中断产生。 系统时钟的频率需要根据芯片的处理能力来决定&#xff0c; 频…

【MySQL基础 | 第一篇】数据处理之基本查询

前言 查询语句属于DML&#xff08;Data Manipulation Language&#xff09;数据操作语言的其中一种&#xff0c;用于从数据库中提取所需的数据。通过灵活的条件和组合&#xff0c;查询语句帮助用户有效地获取、过滤和排序数据&#xff0c;满足各种信息需求。 文章目录 前言1️⃣…

团体程序设计天梯赛-练习集L1篇⑨

&#x1f680;欢迎来到本文&#x1f680; &#x1f349;个人简介&#xff1a;Hello大家好呀&#xff0c;我是陈童学&#xff0c;一个与你一样正在慢慢前行的普通人。 &#x1f3c0;个人主页&#xff1a;陈童学哦CSDN &#x1f4a1;所属专栏&#xff1a;PTA &#x1f381;希望各…

编译原理笔记17:自下而上语法分析(4)LR(0)、SLR(1) 分析表的构造

目录 LR(0) 文法LR(0) 分析表的构造例 SLR(1) 文法SLR 分析表构造 非 SLR(1) 文法举例二义文法都不是 SLR(1) 文法不是二义文法的非 SLR(1) 文法 LR(0) 文法 若一个文法 G 的拓广文法 G’ 的识别活前缀的自动机中的每个状态&#xff08;项目集&#xff09;均不存在下述情况&…

【一文通】C/C++与Go语言混合编程入门级教程(Windows平台完成)

一、概述 Go语言可以通过自带的 cgo 工具进行 CGO 混合编程&#xff0c;这个工具放在go安装目录的 pkg\tool 下&#xff0c;其源代码则在 src\runtime\cgo 里面&#xff0c;当然作为入门教程本文不打算对cgo的实现原理进行深入研究&#xff0c;仅从 Hello World 的角度来实际体…

快速查询银行卡发卡省市和归属银行,了解自己的财务状况!

API接口是现代软件开发的基本组成部分。它们允许应用程序通过互联网连接到其他软件系统&#xff0c;并从这些系统中获取或传输数据。银行卡归属地查询API接口是为开发人员提供的一种工具&#xff0c;可以帮助他们轻松地查询银行卡的归属地信息。在本文中&#xff0c;我们将介绍…

内网横向移动—IPCATschtasks

内网横向移动—IPC&AT&schtasks 1. IPC介绍1.1. IPC利用条件关系1.1.1. IPC$空连接介绍1.1.2. 139与445端口介绍1.1.3. 默认共享 1.2. IPC连接问题1.2.1. IPC连接失败原因1.2.2. IPC连接常见错误 2. 横向移动常用命令2.1. IPC命令介绍2.1.1. IPC常用命令演示2.1.1.1. 建…

docker非root用户下取消sudo前缀

解决非root用户下执行docker命令提示权限不足&#xff0c;必须添加sudo的问题。 第一步&#xff1a;执行 sudo gpasswd aby docker 命令&#xff0c;将当前用户aby加入docker组中。 第二步&#xff1a;执行 sudo chmod arw /var/run/docker.sock 命令修改sock权限

数据结构之堆——算法与数据结构入门笔记(六)

本文是算法与数据结构的学习笔记第六篇&#xff0c;将持续更新&#xff0c;欢迎小伙伴们阅读学习。有不懂的或错误的地方&#xff0c;欢迎交流 引言 当涉及到高效的数据存储和检索时&#xff0c;堆&#xff08;Heap&#xff09;是一种常用的数据结构。上一篇文章中介绍了树和完…

chatgpt赋能python:Python列表转字符串——从新手到大师

Python列表转字符串——从新手到大师 在Python编程中&#xff0c;列表和字符串是非常常用的数据类型。有时候&#xff0c;我们需要将一个列表转换为一个字符串&#xff0c;以方便进行各种操作。幸运的是&#xff0c;Python内置了一些函数和方法&#xff0c;可以轻松地将列表转…

7Z045 引脚功能详解

本文针对7Z045芯片&#xff0c;详细讲解硬件设计需要注意的技术点&#xff0c;可以作为设计和检查时候的参考文件。问了方便实用&#xff0c;按照Bank顺序排列&#xff0c;包含配置Bank、HR Bank、HP Bank、GTX Bank、供电引脚等。 参考文档包括&#xff1a; ds191-XC7Z030-X…

ruoyi-cloud版本(一)项目的下载与本地运行(亲测有效)

目录 1 架构2 架构图3 源码下载4 创建数据库5 下载nacos与运行6 打开运行基础模块&#xff08;启动没有先后顺序&#xff09;7 启动前端 1 架构 com.ruoyi ├── ruoyi-ui // 前端框架 [80] ├── ruoyi-gateway // 网关模块 [8080] ├── ruoyi…

canvas详解00-认识canvas

身为一个WEB开发人员&#xff0c;肯定都是想着能够开发出酷炫和激动人心的应用程序来。可以很多动画特效&#xff0c;例如黑客帝国的数字&#xff0c;彩色炫酷的例子动效。也可以实现各种图画面板&#xff0c;如实现类似于photoshop的web在线图像编辑。各种酷炫的表单等等。 #…