【C++高阶(六)】哈希的应用--位图布隆过滤器

💓博主CSDN主页:杭电码农-NEO💓

⏩专栏分类:C++从入门到精通⏪

🚚代码仓库:NEO的学习日记🚚

🌹关注我🫵带你学习C++
  🔝🔝


在这里插入图片描述

哈希的应用

  • 1. 前言
  • 2. 位图的概念以及定义
  • 3. 位图的模拟实现
  • 4. 布隆过滤器的概念以及定义
  • 5. 布隆过滤器模拟实现(一)
  • 6. 布隆过滤器模拟实现(二)
  • 7. 处理海量数据的面试题
  • 8. 总结

1. 前言

哈希最常用的应用是unordered
系列的容器,但是当面对海量数据
如100亿个数据中找有没有100这
个数时,使用无序容器的话内存放不下
所以哈希思想还有别的更重要的应用!

本章重点:

本篇文章着重讲解哈希的应用的
两个容器,一个是位图,一个是布隆
过滤器,并且模拟实现它们.最后会
讲解如何使用这两个容器来解决一
些海量数据的面试题问题


2. 位图的概念以及定义

请先看一道海量数据的面试题:

在这里插入图片描述

如果要使用unordered_set来解决
40亿个整数,一个整数占4四节,
总共大约占16个G的内存空间
并且set容器中不止有整型数据,还有
其他的数据,所以不能用set!

而一个数在或不在可以用1/0来表示
也就是说其实只需要一个比特位就可
以知道一个数在不在其中.
于是位图横空出世!

位图概念:

所谓位图,就是用每一位来存放某种状态,适用于海量数据,数据无重复的场景。通常是用来判断某个数据存不存在的

举例说明:

在这里插入图片描述

判断1~22中哪些数据是存在的
只需要用三个整型也就是24个
比特位的空间,同理,40亿个数据
也用不着16G的内存,使用0.5G
内存的位图即可判断一个数在不在!


3. 位图的模拟实现

先来看看库中实现的位图:
在这里插入图片描述

模板参数N代表位图的大小

位图有三个主要的接口函数:

  1. set: 将一个数据放入位图中
  2. reset:将一个数据从位图中删掉
  3. test:检测一个数据在不在位图中

位图本身就是一段连续的空间
所以用char类型数组来充当位图的
基本结构是很符合情况的!

先将位图框架写出来:

template<size_t N>//N是所有数中的最大值
class bit_set
{
public:
	bit_set()
	{
		_bit.resize(N / 8 + 1, 0);
	}
	void set(size_t x)//将第x位变成1
	{}
	void reset(size_t x)//将第x位由1变0
	{}
	bool test(size_t x)
	{}
private:
	vector<char> _bit;
};

在写set,reset等函数时,要先清除一点,
那就是char类型的数组一个元素有八个
比特位,所以我们需要确定两个位置:
一是此数据在哪一个数组元素中
二是此数据对应此元素的第几个比特位
下面我们画个图来推导一下公式:

在这里插入图片描述

现在已经能准确的找到这个比特位了
那么怎样将这个比特位变成0/1并且
不会影响到其他的比特位呢?下面分享
两个很巧妙的方法,请大家细细品尝:

template<size_t N>//N是所有数中的最大值
class bit_set
{
public:
	bit_set()
	{
		_bit.resize(N / 8 + 1, 0);
	}
	void set(size_t x)//将第x位变成1
	{
		//x/8->在第几个char
		//x%8->在这个char的第几个比特位
		size_t i = x / 8;
		size_t j = x % 8;
		_bit[i] |= (1 << j);//将x对应的比特位变成1
	}
	void reset(size_t x)
	{
		size_t i = x / 8;
		size_t j = x % 8;
		_bit[i] &= ~(1 << j);//将x对应的比特位变成0
	}
	bool test(size_t x)
	{
		size_t i = x / 8;
		size_t j = x % 8;
		return _bit[i] & (1 << j);
	}
private:
	vector<char> _bit;
};

关于代码的解释都在注释中,请耐心观看
必要时可以自己画图做做试验


4. 布隆过滤器的概念以及定义

位图有一个缺陷,那就是只能判断整型是否存在
遇见字符串等类型的数据就很难处理了

布隆过滤器的提出:

在这里插入图片描述
布隆过滤器的概念:

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

举例说明:

在这里插入图片描述
查找字符"美团"是否存在时,会找到
这三个绿色的位置,看看是否都为1

布隆过滤器的拓展阅读:

布隆过滤器原理


5. 布隆过滤器模拟实现(一)

首先,布隆过滤器的底层也是位图,所以
只需封装一层即可实现一个布隆过滤器!

但实现布隆过滤器的关键有以下几个

  • 一个字符串映射几个位置?
  • 怎样把字符串转换为整数?

一般而言,一个字符串映射的越多,那么
误判率就越低,但是映射过多会导致不同
的字符串映射到相同的位置,所以一般映射
三个位置,并且将字符串转换为整数也就
需要三种不同的方法,我在网上找了一些
字符串转整数的算法,请看下面的代码:

//三个不同的字符串映射成整数的函数
struct HashBKDR
{
	size_t operator()(const string& key)
	{
		size_t val = 0;
		for (auto ch : key)
		{
			val *= 131;
			val += ch;
		}
		return val;
	}
};
struct HashAP
{
	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
{
	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 Bloom_Filter
{
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:
	const static size_t _ratio = 5;//开的空间越大,误判率越小
	std::bitset<_ratio* N>* _bits = new std::bitset<_ratio * N>;//标准库中的位图是在栈上开辟的静态数组,过大会栈溢出
};

6. 布隆过滤器模拟实现(二)

布隆过滤器的查找是一个很玄幻的过程:

分别计算每个哈希值对应的比特位置存储的是否为零,只要有一个为零,代表该元素一定不在哈希表中,否则可能在哈希表中

因为哈希函数可能存在冲突的原因,如下:

在这里插入图片描述
所以我们得出一个结论:

  • 布隆过滤器说一个元素存在,那它可能存在
  • 布隆过滤器说一个元素不在,那它一定不在

布隆过滤器的删除操作:

如果你理解了上面的内容,你一定能
明白布隆过滤器是不支持删除的,因为
删除一个关键字时可能将其他的关键字
的一部分也给删除了,因为一个bit位
只能存储一个二进制信息!

在这里插入图片描述


7. 处理海量数据的面试题

海量数据的处理,有对位图的应用
也有对布隆过滤器的应用一步一步解析

位图的应用:

  1. 给100亿个整数,设法找到只出现一次的整数?
  2. 给两个文件,分别有100亿个整数,只有1G内存,如何找到两个文件交集?
  3. 位图应用变形:一个文件有100亿个int,1G内存,设法找到出现次数不超过2次的所有整数

布隆过滤器的应用:

  1. 给两个文件,分别有100亿个query,我们只有1G内存,如何找到两个文件交集?分别给出精确算法和近似算法
  2. 如何扩展BloomFilter使得它支持删除元素的操作

这些问题大家可以下来想一想,有什么问题欢迎私信


8. 总结

讲到这里,哈希的所有内容就已经
讲完了,所以无脑哈希无脑哈希,
但实际上要学好哈希还真得费点脑子

海量数据得处理问题在面试时也是
经常问的,希望同学们好好学扎实!


🔎 下期预告:C++11新改动🔍

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

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

相关文章

深度学习——Loss汇总

深度学习——Loss汇总 一、IOU Loss二、L1 Loss 一、IOU Loss 公式&#xff1a; 参考资料: 目标检测回归损失函数——IOU、GIOU、DIOU、CIOU、EIOU 二、L1 Loss 公式&#xff1a; 参考资料: PyTorch中的损失函数–L1Loss /L2Loss/SmoothL1Loss

【FMC140】 基于VITA57.4标准的双通道5.2GSPS(或单通道10.4GSPS)射频采样FMC+子卡模块

板卡概述 FMC140是一款具有缓冲模拟输入的低功耗、12位、双通道&#xff08;5.2GSPS/通道&#xff09;、单通道10.4GSPS、射频采样ADC模块&#xff0c;该板卡为FMC标准&#xff0c;符合VITA57.1规范&#xff0c;该模块可以作为一个理想的IO单元耦合至FPGA前端&#xff0c;8通道…

<avue-crud/>,二级表头,children下字典项的dicUrl失效问题

目录 1.提出问题&#xff1a; 1.1 代码&#xff1a; 1.2 效果图&#xff1a;会发现处在children下的dicUrl失效了 2. 解决思路 3. 解决代码&#xff08;你要的都在这&#xff0c;看这里&#xff09; 1.提出问题&#xff1a; 在使用<avue-crud/>组件实现二级表头时&…

Leetcode2336 无限集中的最小数字

题目&#xff1a; 现有一个包含所有正整数的集合 [1, 2, 3, 4, 5, ...] 。 实现 SmallestInfiniteSet 类&#xff1a; SmallestInfiniteSet() 初始化 SmallestInfiniteSet 对象以包含 所有 正整数。int popSmallest() 移除 并返回该无限集中的最小整数。void addBack(int nu…

Linux | Ubuntu设置 netstat(网络状态)

netstat命令用于显示与IP、TCP、UDP和ICMP协议相关的统计数据&#xff0c;一般用于检验本机各端口的网络连接情况。netstat是在内核中访问网络及相关信息的程序&#xff0c;它能提供TCP连接&#xff0c;TCP和UDP监听&#xff0c;进程内存管理的相关报告。 1.netstat的安装 搜…

nodejs最新电商jd m端h5st 4.2签名算法4.2版本逆向,jd API接口,jd商品数据采集

前言&#xff1a; jd m端使用最新的h5st 4.2签名算法&#xff0c;与h5st 4.1版本有很大的不同。在这儿分析一下&#xff0c;供大家参考。 一、目标地址(Base64解码) aHR0cHM6Ly9zby5tLmpkLmNvbS93YXJlL3NlYXJjaC5hY3Rpb24/a2V5d29yZD0lRTklOTklQTQlRTYlQjklQkYlRTYlOUMlQkEmc2…

c++基本常见错误总结

我们无论是在学习中还是在工作当中&#xff0c;总是会遇到各种各样的c编译错误问题&#xff0c;经常会有一种情况就是上一次好像遇到过这种问题&#xff0c;但是就是想不起来了&#xff08;我就是这样&#xff09;所以下面这一篇文章就是总结自己遇到的编译以及运行错误。 注意…

药食同源的食物哪些适合冬季吃?

药食同源的食物是指在中医理论指导下&#xff0c;既是药物又是食物的天然植物和动物&#xff0c;具有营养和药效双重作用。在冬季&#xff0c;由于气候寒冷&#xff0c;人体需要更多的热量和营养来保持温暖和健康&#xff0c;因此药食同源的食物在冬季特别适合食用。以下是几种…

(5h)Unity3D快速入门之Roll-A-Ball游戏开发

DAY1&#xff1a;Unity3D安装 链接 DAY2&#xff1a;构建场景&#xff0c;编写代码 链接 内容&#xff1a;WASD前后左右移动、摄像机跟随 DAY3&#xff1a;待更新 DAY4&#xff1a;待更新 DAY5&#xff1a;待更新

UG\NX二次开发 设置是否允许通过NXOpen锁定属性

文章作者:里海 来源网站:里海NX二次开发3000例专栏 感谢粉丝订阅 感谢 2301_80939425 订阅本专栏,非常感谢。 简介 在使用UF_ATTR_set_locked函数锁定属性前,需要先设置是否允许通过NXOpen锁定属性。使用下面的代码可以修改“用户默认设置”当 NX 启动时,客户默认值将读取…

TA-Lib学习研究笔记(三)——Volatility Indicator

TA-Lib学习研究笔记&#xff08;三&#xff09;——Volatility Indicator 波动率指标函数组 Volatility Indicators: [‘ATR’, ‘NATR’, ‘TRANGE’] 1.ATR Average True Range 函数名&#xff1a;ATR 名称&#xff1a;真实波动幅度均值 简介&#xff1a;真实波动幅度均值…

第二十章多线程总结

20.1 线程简介 世间有很多工作都是可以同时完成的。例如&#xff0c;人体可以同时进行呼吸、血液循环、思考问题等活用户既可以使用计算机听歌&#xff0c;也可以使用它打印文件。同样&#xff0c;计算机完全可以将多种活动同时进这种思想放在 Java 中被称为并发&#xff0c;而…

深度学习框架:Pytorch与Keras的区别与使用方法

☁️主页 Nowl &#x1f525;专栏《机器学习实战》 《机器学习》 &#x1f4d1;君子坐而论道&#xff0c;少年起而行之 文章目录 Pytorch与Keras介绍 Pytorch 模型定义 模型编译 模型训练 输入格式 完整代码 Keras 模型定义 模型编译 模型训练 输入格式 完整代…

【网络安全】-安全常见术语介绍

文章目录 介绍1. 防火墙&#xff08;Firewall&#xff09;定义通俗解释 2. 恶意软件&#xff08;Malware&#xff09;定义通俗解释 3. 加密&#xff08;Encryption&#xff09;定义通俗解释 4. 多因素认证&#xff08;Multi-Factor Authentication&#xff0c;MFA&#xff09;定…

springMVC实验(二)—调式工具APIFOX的使用

【知识要点】 后端开发调试工具 前后端分离已经成为互联网类软件开发主流模式&#xff0c;没有前端操作的支持&#xff0c;如何调试后端程序的就是开发人员必须解决的问题。如&#xff1a;get类请求可以直接使用浏览器就能模拟测试&#xff0c;但是post、put等类型的请求&…

22款奔驰GLS450升级香氛负离子 淡淡的幽香

香氛负离子系统是由香氛系统和负离子发生器组成的一套配置&#xff0c;也可以单独加装香氛系统或者是负离子发生器&#xff0c;香氛的主要作用就是通过香氛外壳吸收原厂的香水再通过空调管输送到内饰中&#xff0c;而负离子的作用就是安装在空气管中通过释放电离子来打击空气中…

支持向量机,硬间隔,软间隔,核技巧,超参数设置,分类与回归

SVM&#xff08;Support Vector Machine&#xff0c;支持向量机&#xff09;是一种非常常用并且有效的监督学习算法&#xff0c;在许多领域都有广泛应用。它可以用于二分类问题和多分类问题&#xff0c;并且在处理高维数据和特征选择方面非常强大。SVM算法的核心思想是通过找到…

nodejs 沙盒逃逸

1.[GFCTF 2021]ez_calc 一道很有意思的一道nodejs的题 沙箱逃逸和绕过&#xff1a; F12 看源码 if(req.body.username.toLowerCase() ! admin && req.body.username.toUpperCase() ADMIN && req.body.passwd admin123){ // 登录成功&am…

Windows下命令行启动与关闭WebLogic的相关服务

WebLogic 的服务器类型 WebLogic提供了三种类型的服务器&#xff1a; 管理服务器节点服务器托管服务器 示例和关系如下图&#xff1a; 对应三类服务器&#xff0c; 就有三种启动和关闭的方式。本篇介绍使用命令行脚本的方式启动和关闭这三种类型的服务器。 关于WebLogic 的…

分布式架构demo

1、外层创建pom 版本管理器 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.15</version><relativePath/> <!-- lookup parent from repository…
最新文章