【C++/STL】:哈希的应用 -- 位图布隆过滤器
目录
- 🚀🚀前言
- 一,位图
- 1. 位图的概念
- 2. STL库中的位图
- 3. 位图的设计
- 4. 位图的模拟实现
- 5. 位图的优缺点
- 6. 位图相关考察题⽬
- 二,布隆过滤器
- 1. 布隆过滤器的概念
- 2. 布隆过滤器的实现
- 3. 布隆过滤器删除问题
- 4. 布隆过滤器的优缺点
点击跳转至文章: 【C++/STL】:哈希 – 线性探测&哈希桶
🚀🚀前言
在前面的文章里我们已经学习了什么是哈希和以哈希表为底层的unordered系列容器的使用。本篇文章的位图&布隆过滤器也是哈希思想下的产物,经常使用它们来解决有关海量数据的问题。
一,位图
1. 位图的概念
在引出位图的概念之前,先来看一个经典面试题:
深入分析:
解题思路2是否可行,我们先算算40亿个数据⼤概需要多少内存。
1G = 1024MB =1024 * 1024KB = 1024*1024 * 1024byte约等于10亿多byte,那么40亿个整数约等于16G,说明40亿个数是无法直接放到内存中的,只能放到硬盘文件中。而二分查找只能对内存数组中的有序数据进行查找。
解题思路3:数据是否在给定的整形数据中,结果是在或者不在,刚好是两种状态,那么可以使⽤⼀个⼆进制⽐特位来代表数据是否存在的信息,如果⼆进制⽐特位为1,代表存在,为0代表不存在。
那么我们设计⼀个⽤二进制比特位表⽰数据是否存在的数据结构,这个数据结构就叫位图。
2. STL库中的位图
根据文档可知,位图bitset 是非类型模板,N是指需要多少比特位。使用时需要包含头文件:
#include <bitset>
位图常用的核心接口主要有三个:
(1) x 映射位标记成1(插入 x,有这个数据了)
(2) x 映射位标记成0(删除 x,没有这个数据了)
(3) 检查是否存在这个数据
x映射的位是1,返回真
x映射的位是0,返回假
3. 位图的设计
位图本质是⼀个直接定址法的哈希表,每个整型值映射⼀个bit位,位图提供控制这个bit的相关接口。
实现中需要注意的是,C/C++没有对应位的类型,只能看int/char这样整形类型,我们再通过位运算去控制对应的⽐特位。⽐如我们数据存到vector< int >中,相当于每个int值映射对应的32个值,⽐如第⼀个整形映射0-31对应的位,第⼆个整形映射32-63对应的位,后⾯的以此类推,那么来了⼀个整形值x,i = x / 32;j = x % 32;计算出x映射的值在vector的第 i 个整形数据的第 j 位。
4. 位图的模拟实现
#include<vector>//非类型模板参数。需要多少比特位
template <size_t N>
class bitset
{
public:bitset(){_bs.resize(N / 32 + 1);}//x映射位标记成1void set(size_t x){//映射的位置:第i个整型数据的第j位size_t i = x / 32;size_t j = x % 32;_bs[i] |= (1 << j);}//x映射位标记成0void reset(size_t x){size_t i = x / 32;size_t j = x % 32;_bs[i] &= (~(1 << j));}//x映射的位是1,返回真//x映射的位是0,返回假bool test(size_t x){size_t i = x / 32;size_t j = x % 32;return _bs[i] & (1 << j);}
private:vector<size_t> _bs;
};
5. 位图的优缺点
优点:增删查改快,节省空间
缺点:只适⽤于整形
6. 位图相关考察题⽬
深入分析:
第一题和第三题是同一类型的题,我们先来分析这两题。首先我们知道把数据放入位图中只能标记在或不在两种状态,而题目要求的是找出出现几次的数据,可能是出现0次,1次……,显然单用一个位图的一个比特位是无法满足的。
用两个位图的标记就可以解决。我们规定00表示数据出现0次,01表示数据出现1次,10表示数据出现2次,11表示数据出现3次及以上
代码实现如下:
注意:这里用的bitset是上文我们自己实现的bitset。
我们针对第一题和第三题设计一个结构:
template<size_t N>
class twobitset
{
public:void set(size_t x){bool bit1 = _bs1.test(x);bool bit2 = _bs2.test(x);if (!bit1 && !bit2) // 00->01{_bs2.set(x);}else if (!bit1 && bit2) // 01->10{_bs1.set(x);_bs2.reset(x);}else if (bit1 && !bit2) // 10->11{_bs1.set(x);_bs2.set(x);}}// 返回0 出现0次数// 返回1 出现1次数// 返回2 出现2次数// 返回3 出现2次及以上int get_count(size_t x){bool bit1 = _bs1.test(x);bool bit2 = _bs2.test(x);if (!bit1 && !bit2){return 0;}else if (!bit1 && bit2){return 1;}else if (bit1 && !bit2){return 2;}else{return 3;}}private:bitset<N> _bs1;bitset<N> _bs2;
};//测试代码,可以统计出100以内哪个数据出现了几次
void test_twobitset()
{twobitset<100> tbs; //开100个bit位int a[] = { 5,7,9,2,5,99,5,5,7,5,3,9,2,55,1,5,6,6,6,6,7,9 };for (auto e : a){tbs.set(e);}for (size_t i = 0; i < 100; ++i){cout << i << "->" << tbs.get_count(i) << endl;//if (tbs.get_count(i) == 1 || tbs.get_count(i) == 2)//cout << i << endl;}
}
第二题的代码实现:
把数据分别放入两个位图中,如果两个位图的标记均为1,说明都存在,就是二者的交集。
void test_bitset1()
{int a1[] = { 5,7,9,2,5,99,5,5,7,5,3,9,2,55,1,5,6 };int a2[] = { 5,3,5,99,6,99,33,66 };bit::bitset<100> bs1;bit::bitset<100> bs2;for (auto e : a1)bs1.set(e);for (auto e : a2)bs2.set(e);for (size_t i = 0; i < 100; i++){if (bs1.test(i) && bs2.test(i))cout << i << endl;}
}
二,布隆过滤器
有⼀些场景下⾯,有⼤量数据需要判断是否存在,⽽这些数据不是整形,那么位图就不能使⽤了,使⽤红⿊树/哈希表等内存空间可能不够。这些场景就需要布隆过滤器来解决。
1. 布隆过滤器的概念
布隆过滤器是⼀种可以⽤来告诉你"某样东西⼀定不存在或者可能存在"的数据结构,它是⽤多个哈希函数,将⼀个数据映射到位图结构中。
布隆过滤器的思路就是把key先映射转成哈希整型值,再映射⼀个位,如果只映射⼀个位的话,冲突率会⽐较多,所以可以通过多个哈希函数映射多个位,降低冲突率。
布隆过滤器这⾥跟哈希表不⼀样,它⽆法解决哈希冲突的,因为他压根就不存储这个值,只标记映射的位。它的思路是尽可能降低哈希冲突。判断⼀个值key在是不准确的,判断⼀个值key不在是准确的。
2. 布隆过滤器的实现
说明:我们这里用的bitset是我们上文自己实现的bitset,不是库里的。
#include "BitSet.h"
#include <string>struct HashFuncBKDR
{size_t operator()(const std::string& s){size_t hash = 0;for (auto ch : s){hash *= 31;hash += ch;}return hash;}
};struct HashFuncAP
{ size_t operator()(const std::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 HashFuncDJB
{size_t operator()(const std::string& s){size_t hash = 5381;for (auto ch : s)hash = hash * 33 ^ ch;return hash;}
};//要用多个哈希函数多映射几个位,以便降低哈希冲突
template <size_t N,size_t X = 5,class K = string,class Hash1 = HashFuncBKDR,class Hash2 = HashFuncAP,class Hash3 = HashFuncDJB>
class BloomFilter
{
public: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);}//如果其中一个位为0,就确定不在,如果都为1,那就在(存在误判)bool Test(const K& key){size_t hash1 = Hash1()(key) % M;if (!_bs.test(hash1))return false;size_t hash2 = Hash2()(key) % M;if (!_bs.test(hash2))return false;size_t hash3 = Hash3()(key) % M;if (!_bs.test(hash3))return false;return true;}
private:static const size_t M = N * X; //布隆过滤器的bit长度bit::bitset<M> _bs;
};//测试代码
void TestBloomFilter1()
{BloomFilter<10> bf;bf.Set("猪八戒");bf.Set("孙悟空");bf.Set("唐僧");cout << bf.Test("猪八戒") << endl;cout << bf.Test("孙悟空") << endl;cout << bf.Test("唐僧") << endl;cout << bf.Test("沙僧") << endl;cout << bf.Test("猪八戒1") << endl;cout << bf.Test("猪戒八") << endl;
}
3. 布隆过滤器删除问题
布隆过滤器默认是不⽀持删除的,因为⽐如"猪⼋戒“和”孙悟空“都映射在布隆过滤器中,他们映射的位有⼀个位是共同映射的(冲突的),如果我们把孙悟空删掉,那么再去查找“猪⼋戒”会查找不到,因为那么“猪⼋戒”间接被删掉了。
4. 布隆过滤器的优缺点
优点:增删查改快,节省空间
缺点:只适⽤于整形
相关文章:

【C++/STL】:哈希的应用 -- 位图布隆过滤器
目录 🚀🚀前言一,位图1. 位图的概念2. STL库中的位图3. 位图的设计4. 位图的模拟实现5. 位图的优缺点6. 位图相关考察题⽬ 二,布隆过滤器1. 布隆过滤器的概念2. 布隆过滤器的实现3. 布隆过滤器删除问题4. 布隆过滤器的优缺点 点击…...

非线性面板数据实证模型及 Stata 具体操作步骤
目录 一、引言 二、文献综述 三、理论原理 四、实证模型 五、稳健性检验 六、程序代码及解释 一、引言 在当今的经济和社会研究中,非线性面板数据模型的应用日益广泛。这类模型能够更好地捕捉数据中的复杂关系,为研究者提供更深入和准确的分析结果。…...

视角 | 麻省理工学院提出出温度计校准法,专治AI大模型过度自信
在数字化浪潮的推动下,人工智能(AI)正成为塑造未来的关键力量。硅纪元视角栏目紧跟AI科技的最新发展,捕捉行业动态;提供深入的新闻解读,助您洞悉技术背后的逻辑;汇聚行业专家的见解,…...

昇思25天学习打卡营第XX天|CycleGAN图像风格迁移互换
CycleGAN是一种用于图像到图像翻译的生成对抗网络,它突破了传统域迁移模型的限制,无需成对样本即可学习图像在不同域间的转换。这种无监督的方法特别适用于难以获取配对数据的场景,例如艺术风格迁移。与需要成对训练样本的Pix2Pix不同&#x…...
嵌入式Linux学习: interrupt实验
Linux中的Interrupt(中断)系统是一个至关重要的组成部分,它负责管理和处理系统中发生的各种硬件和软件中断,确保系统能够正确响应外部设备的请求,保持系统的稳定性和可靠性。 1.中断的作用 允许设备在没有CPU干预的情…...
GPT-4o mini 来袭:开发者如何驾驭新一代AI模型?
GPT-4o Mini 来袭:开发者如何驾驭新一代 AI 模型? 引言 随着人工智能(AI)技术的飞速发展,越来越多的先进模型不断涌现,给各行各业带来了深远的影响。OpenAI 最新推出的 GPT-4o Mini 是一种创新的 AI 模型…...

校园点餐系统
1 项目介绍 1.1 摘要 在这个被海量信息淹没的数字化时代,互联网技术以惊人的速度迭代,信息的触角无处不在,社会的脉动随之加速。每一天,我们都被汹涌而至的数据浪潮包裹,生活在一个全方位的数字信息矩阵中。互联网的…...

进口不锈钢309S螺栓的应用优势
进口不锈钢309S螺栓因其优异的性能和广泛的应用范围而在许多行业中备受青睐。309S不锈钢是一种含硫的易切削不锈钢,具有良好的耐高温和耐腐蚀性能,使其成为高温环境下理想的选择。下面我们就来详细探讨一下进口不锈钢309S螺栓的应用优势。 一、309S不锈钢…...
C# 设计模式之工厂方法模式
总目录 前言 本文是个人基于C#学习设计模式总结的学习笔记,希望对你有用! 在简单工厂模式中说到了简单工厂模式的缺点:简单工厂模式系统难以扩展,一旦添加新产品就不得不修改简单工厂方法,这样就会造成简单工厂的实现…...

Webpack 从入门到精通
(创作不易,感谢有你,你的支持,就是我前行的最大动力,如果看完对你有帮助,请留下您的足迹) 目录 一、Webpack 简介 二、Webpack 的核心概念 三、Webpack 的安装与配置 安装 Node.js 安装 Webpack 初始…...

基于VScode和C++ 实现Protobuf数据格式的通信
目录 1. Protobuf 概述1.1 定义1.2Protobuf的优势 2. Protobuf 语法3、序列号和反序列化3.1 .pb.h 头文件3.2 序列化3.3 反序列化 4、测试用例 Protobuf详细讲解链接 1. Protobuf 概述 1.1 定义 protobuf也叫protocol buffer是google 的一种数据交换的格式,它独立…...
linux环境openssl升级
1、下载openssl https://openssl-library.org/source/ 或者通过wget --no-check-certificate https://www.openssl.org/source/openssl-3.0.13.tar.gz 2、解压openssl tar -zxvf openssl-3.0.13.tar.gz 3、切换到解压后的目录 cd openssl-3.0.13/ 4、配置openssl安装目录…...

150Kg载重遥控履带式无人车技术详解
150Kg载重遥控履带式无人车是一种专为复杂地形和重载运输设计的无人化智能平台。它结合了先进的动力技术、履带式行走机构、远程遥控系统、高精度感知与导航技术及模块化设计,能够在恶劣环境下执行物资运输、侦察监视、灾害救援等多种任务。该车以其卓越的越野能力、…...

STM32的外部中断详解
一、什么是中断? 想象一下你正在家里做饭,突然门铃响了,你听到门铃声后,会暂时放下手中的事情(比如炒菜),去开门看看是谁。在这个例子中,门铃声就是一个“中断”,它打断…...

关于python问题 ,生成的excel文件内无爬取的数据存在,请问应如何解决?
🏆本文收录于《CSDN问答解惑-专业版》专栏,主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收…...
详细介绍Avalonia中的文件操作StorageProvider服务
文章目录 一、介绍二、StorageProvider的原理三、StorageProvider的实现1. 创建文件选择和保存对话框2. 选择目录四、StorageProvider的配置五、StorageProvider的高级用法1. 读取和写入文件2. 获取文件和目录信息3. 管理文件和目录4. 处理不同平台的差异六、总结一、介绍 在桌…...

「7.31更新日志」JVS·智能BI、逻辑、规则引擎功能更新说明
项目介绍 JVS是企业级数字化服务构建的基础脚手架,主要解决企业信息化项目交付难、实施效率低、开发成本高的问题,采用微服务配置化的方式,提供了 低代码数据分析物联网的核心能力产品,并构建了协同办公、企业常用的管理工具等&am…...

编程语言 | C | 代码整理 | 4月
八月拍了拍你,并对你说:“好运就要开始了”! 目录 编程语言 | C | 代码整理 | 4月2019/4/12019/4/22019/4/22019/4/32019/4/42019/4/52019/4/62019/4/72019/4/82019/4/92019/4/102019/4/112019/4/122019/4/132019/4/142019/4/152019/4/162019…...
模板可变参数
当涉及到 C 编程中的模板参数处理时,特别是在处理可变数量的参数时,模板可变参数(variadic templates)是一个非常有用的特性。本篇博客将深入介绍模板可变参数的基本概念、语法、应用场景以及示例代码,帮助读者理解如何…...

是你!是你!我们的黄金写手!
...

转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...
工程地质软件市场:发展现状、趋势与策略建议
一、引言 在工程建设领域,准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具,正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...

Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...

selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...

Spring数据访问模块设计
前面我们已经完成了IoC和web模块的设计,聪明的码友立马就知道了,该到数据访问模块了,要不就这俩玩个6啊,查库势在必行,至此,它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据(数据库、No…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容
目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...
Java 二维码
Java 二维码 **技术:**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...

基于 TAPD 进行项目管理
起因 自己写了个小工具,仓库用的Github。之前在用markdown进行需求管理,现在随着功能的增加,感觉有点难以管理了,所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD,需要提供一个企业名新建一个项目&#…...

基于Java+MySQL实现(GUI)客户管理系统
客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息,对客户进行统一管理,可以把所有客户信息录入系统,进行维护和统计功能。可通过文件的方式保存相关录入数据,对…...

2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)
安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...