C++——哈希的应用(位图、布隆)

目录

前言

一、位图、布隆是什么?

二、位图

1.面试题

2.位运算

3 位图的应用

三、布隆过滤器

1、代码实现 

2、 布隆过滤器的查找

3、 布隆过滤器删除

4、 布隆过滤器优点

5、 布隆过滤器缺陷

总结



前言

我们学习了哈希算法,我们知道存储数据可以构建一种函数来映射数据存储的位置。


一、位图、布隆是什么?

位图(Bitmap):位图是一种使用二进制位来表示数据的存在与否的数据结构。在位图中,每个元素通常映射到一个位(bit),如果该元素存在于集合中,则对应的位被设置为1;否则为0。位图适用于大规模数据且无重复的场景,可以极大地节省存储空间并提高查询效率。例如,在数据库索引、图像处理等领域有广泛应用。
布隆过滤器(Bloom Filter):布隆过滤器是由一系列哈希函数和一个二进制位数组构成的概率型数据结构。当一个元素被加入集合时,通过多个哈希函数将其映射到位数组上的多个位置,并将对应位置的二进制位设为1。查询时,如果元素被映射的所有位置都为1,则认为元素可能在集合中,但存在误判的可能性。布隆过滤器适用于需要高效插入和查询,同时能容忍一定误判率的场景,如垃圾邮件过滤、网页爬虫去重等。

二、位图

1.面试题

1. 面试题 给40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何快速判断一个数是否在 这40亿个数中。【腾讯】

1. 遍历,时间复杂度O(N)

2. 排序(O(NlogN)),利用二分查找: logN

3. 位图解决 数据是否在给定的整形数据中,结果是在或者不在,刚好是两种状态,那么可以使用一 个二进制比特位来代表数据是否存在的信息,如果二进制比特位为1,代表存在,为0 代表不存在。比如:

我们知道整数在内存里面存储是以一个一个的二进制数字的方式存储的,一个整数需要占4个字节,一个字节占8个bit位,那么一个整数就需要32个bit位,40亿个整型存储在内存中就需要大约16GB的内存,而用位图我们就只需要40亿个bit位就可以了,也就是5亿个字节,也就是512MB。而我们学习完位图,我们定义了一个char类型的数组,比如我们存储10,我们就知道我们需要将下标位1的那个字节中第2个bit位改为一;

2.位运算


按位与:&
按位与的定义是:同一二进制位上的数字都是1的话,&的结果为1,否则为0.

0 & 0 = 0;

0 & 1 = 0;

1 & 1 = 1;

不同大小的数据位操作的原则,低位对齐,高位补零。

根据这个特性,&操作常常用来屏蔽特定的二进制位。例如:

​ 0000 1111 & 0000 0011

​ 结果为0000 0011.可以看见,1111的前两位被屏蔽成为0了。

​ 所以如果想清空数据,只需要将原二进制数与上0就可以了。0的位数对应原二进制数的位数,对各位进行屏蔽,全部置0.

​ 相对的,&可以利用0来屏蔽,也可以用1来读取。

​ 例如: 一个二进制数 1101 1001,我只想要它的后四位,怎么办呢?

​ 只需要进行如下操作:1101 1001 & 0000 1111即可。

​ 其实该方法是屏蔽和读取的结合,&0保证消除无用位,&1保证有用数据的完整性。

​ 总结:对于原二进制数来说,&0是屏蔽,&1是不变。


按位或(OR):|
定义:只要参与运算的双方其中有一个是1,结果就是1.同0才为0.

0 | 0 = 0;

0 | 1 = 1;

1 | 0 = 1;

1 | 1 = 1;

不同大小的数据位操作的原则,低位对齐,高位补零。

将某些特定位置1.

例如:1010 0000 | 0000 1111.

结果为 1010 1111.

总结:对于原二进制数来说,|0是不变,|1是置1.


按位异或:^
只要参与运算的双方互异,结果就为1,否则为0.

0 ^ 1 = 1;

1 ^ 0 = 1;

1 ^ 1 = 0;

0 ^ 0 = 0;

不同大小的数据位操作的原则,低位对齐,高位补零。

用法

可以通过上面的定义看到,一个数1的话就会0变成1,1变成0,而0则不对原数进行改变。所以根据此特性可以对特定位进行0 1 反转。

例如: 1100 1100 ^ 0000 1100

结果为 1100 0000.

同样的,如果对一个数进行^0,代表保留原值。


取反(~)
​ 对一个二进制数进行取反。1变0,0变1.

​ 唯一需要注意的一点是,~的优先级是逻辑运算符中最高的,必须优先计算。


左移<<
用法

对运算符<<左边的运算量的每一位全部左移右边运算量表示的位数,右边空出的位补0。

左移<<的原则是高位舍弃,低位补零。

例:char a=0x21;

则a<<2的过程 0010 0001〈〈2 = 1000 0100;即 a<<2的值为0x84。

左移1位相当于该数乘以2,左移n位相当于该数乘以2n。


右移>>
用法

运算规则:对运算符>>左边的运算量的每一位全部右移右边运算量表示的位数,右边低位被移出去舍弃掉,空出的高位补0还是补1,分两种情况:

(1)对无符号数进行右移时,空出的高位补0。这种右移称为逻辑右移。

(2)对带符号数进行右移时,空出的高位全部以符号位填补。即正数补0,负数补1。这种右移称为算术右移。

代码如下(示例):

class bitset
{
public:bitset(){_bits.resize(N/8 + 1, 0);}void set(size_t x){size_t i = x / 8;//判断第几个字节size_t j = x % 8;//第几个比特位//_bits这个数组初始化全为0//1的二进制位0000 0001//将它左移j位//设x位10,则左移后为0000 0100//在与0或就为0000 0100//则这个字节存储的数应给为04_bits[i] |= (1 << j);//}void reset(size_t x){size_t i = x / 8;size_t j = x % 8;_bits[i] &= ~(1 << j);}bool test(size_t x){size_t i = x / 8;size_t j = x % 8;return _bits[i] & (1 << j);}private:vector<char> _bits;
};

3 位图的应用

1. 快速查找某个数据是否在一个集合中

2. 排序 + 去重

3. 求两个集合的交集、并集等

4. 操作系统中磁盘块标记  

三、布隆过滤器

1 布隆过滤器提出 我们在使用新闻客户端看新闻时,它会给我们不停地推荐新的内容,它每次推荐时要去重,去掉 那些已经看过的内容。问题来了,新闻客户端推荐系统如何实现推送去重的? 用服务器记录了用 户看过的所有历史记录,当推荐系统推荐新闻时会从每个用户的历史记录里进行筛选,过滤掉那 些已经存在的记录。 如何快速查找呢?

1. 用哈希表存储用户记录,

缺点:浪费空间

2. 用位图存储用户记录,

缺点:位图一般只能处理整形,如果内容编号是字符串,就无法处理 了。

3. 将哈希与位图结合,即布隆过滤器

详解布隆过滤器的原理,使用场景和注意事项

2.3 布隆过滤器的插入 

 

 

我们发现在想布隆过滤器中插入一个字符串时,我们通过多种映射关系,将它映射在不同的位置,这要就避免了哈希碰撞。

1、代码实现 

template<size_t N>
class twobitset
{
public:void set(size_t x){// 00 -> 01if (_bs1.test(x) == false&& _bs2.test(x) == false){_bs2.set(x);}else if (_bs1.test(x) == false&& _bs2.test(x) == true){// 01 -> 10_bs1.set(x);_bs2.reset(x);}// 10}void Print(){for (size_t i = 0; i < N; ++i){if (_bs2.test(i)){cout << i << endl;}}}public:bitset<N> _bs1;bitset<N> _bs2;
};

布隆过滤器搭建在位图之上的,然后通过各种映射关系将不同的地方改为1或0 

2、 布隆过滤器的查找

布隆过滤器的思想是将一个元素用多个哈希函数映射到一个位图中,因此被映射到的位置的比特 位一定为1。所以可以按照以下方式进行查找:分别计算每个哈希值对应的比特位置存储的是否为 零,只要有一个为零,代表该元素一定不在哈希表中,否则可能在哈希表中。

注意:布隆过滤器如果说某个元素不存在时,该元素一定不存在,如果该元素存在时,该元素可 能存在,因为有些哈希函数存在一定的误判。

比如:在布隆过滤器中查找"alibaba"时,假设3个哈希函数计算的哈希值为:1、3、7,刚好和其 他元素的比特位重叠,此时布隆过滤器告诉该元素存在,但实该元素是不存在的。

3、 布隆过滤器删除

布隆过滤器不能直接支持删除工作,因为在删除一个元素时,可能会影响其他元素。

比如:删除上图中"tencent"元素,如果直接将该元素所对应的二进制比特位置0,“baidu”元素也 被删除了,因为这两个元素在多个哈希函数计算出的比特位上刚好有重叠。 一种支持删除的方法:将布隆过滤器中的每个比特位扩展成一个小的计数器,插入元素时给k个计 数器(k个哈希函数计算出的哈希地址)加一,删除元素时,给k个计数器减一,通过多占用几倍存储 空间的代价来增加删除操作。

缺陷:

1. 无法确认元素是否真正在布隆过滤器中

2. 存在计数回绕

4、 布隆过滤器优点

1. 增加和查询元素的时间复杂度为:O(K), (K为哈希函数的个数,一般比较小),与数据量大小无 关 2. 哈希函数相互之间没有关系,方便硬件并行运算

3. 布隆过滤器不需要存储元素本身,在某些对保密要求比较严格的场合有很大优势

4. 在能够承受一定的误判时,布隆过滤器比其他数据结构有这很大的空间优势

5. 数据量很大时,布隆过滤器可以表示全集,其他数据结构不能

6. 使用同一组散列函数的布隆过滤器可以进行交、并、差运算

5、 布隆过滤器缺陷

1. 有误判率,即存在假阳性(False Position),即不能准确判断元素是否在集合中(补救方法:再 建立一个白名单,存储可能会误判的数据)

2. 不能获取元素本身

3. 一般情况下不能从布隆过滤器中删除元素

4. 如果采用计数方式删除,可能会存在计数回绕问题


总结

位图(Bitmap):位图是一种使用二进制位来表示数据的存在与否的数据结构。在位图中,每个元素通常映射到一个位(bit),如果该元素存在于集合中,则对应的位被设置为1;否则为0。位图适用于大规模数据且无重复的场景,可以极大地节省存储空间并提高查询效率。例如,在数据库索引、图像处理等领域有广泛应用。
布隆过滤器(Bloom Filter):布隆过滤器是由一系列哈希函数和一个二进制位数组构成的概率型数据结构。当一个元素被加入集合时,通过多个哈希函数将其映射到位数组上的多个位置,并将对应位置的二进制位设为1。查询时,如果元素被映射的所有位置都为1,则认为元素可能在集合中,但存在误判的可能性。布隆过滤器适用于需要高效插入和查询,同时能容忍一定误判率的场景,如垃圾邮件过滤、网页爬虫去重等。

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

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

相关文章

应对延迟退休:智能AI如何帮我们?

延迟退休已经成为了当下的热门话题。随着我国人口老龄化的加剧&#xff0c;如何合理延长劳动者的职业生涯并保持他们的工作积极性&#xff0c;已经成了社会关注的焦点。这不仅仅是政策的调整&#xff0c;更是对个人生活、职业规划、健康管理等方面的全方位挑战。 许多人对延迟…

音频左右声道数据传输_2024年9月6日

如下为音频数据传输标准I2S总线的基本时序图 I2S slave将I2S master发送来的左右声道的串行数据DATA转变为16bit的并行数据 WS为左右声道选择信号&#xff0c;WS高代表左声道&#xff0c;WS低代表右声道; WS为高和为低都持续18个周期&#xff0c;前面16个周期用来传输数据。 I2…

【Hot100】LeetCode—32. 最长有效括号

目录 1- 思路题目识别动态规划 2- 实现⭐32. 最长有效括号——题解思路 3- ACM 实现 原题链接&#xff1a;32. 最长有效括号 1- 思路 题目识别 识别1 &#xff1a;给定一个字符串 s &#xff0c;求解 s 中的最长有效括号 动态规划 动态规划五部曲 递推公式难如果遇到了 s.…

如何在Linux下升级R版本和RStudio

一、升级R版本 在Linux上&#xff0c;R的安装通常通过包管理器完成。不同的Linux发行版&#xff08;如Ubuntu、Debian、Fedora等&#xff09;可能略有不同。下面以Ubuntu为例&#xff0c;介绍如何升级R版本。如果你使用其他发行版&#xff0c;步骤可能类似。 二.更新步骤 2.…

MySQL —— 视图

概念 视图是一张虚拟的表&#xff0c;它是基于一个或多个基本表或其他视图的查询结果集。 视图本身不存储数据&#xff0c;而是通过执行查询来动态生成数据&#xff0c;用户可以像操作普通表一样使用视图来进行查询更新与管理等操作。 视图本身也不占用物理存储空间&#xf…

NC 排序

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女通用&#xff0c;看懂了就去分享给你的码吧。 描述 给定一个长度…

时序约束进阶三:Create_clock与Create_Generated_Clock详解

目录 一、前言 二、生成时钟 2.1 示例设计 2.2 主时钟约束 1&#xff09;约束对象解析 2&#xff09;约束到非时钟位置 2.3 生成时钟约束 1&#xff09;无约束 2&#xff09;倍频约束 3&#xff09;生成时钟的主时钟约束不正确 4&#xff09;使能时钟控制的约束 5&…

格式化u盘选择FAT还是NTFS U盘和硬盘格式化两者选谁

Mac用户在将U盘或硬盘进行格式化时&#xff0c;选择FAT还是NTFS往往是一个让人纠结的问题。很多用户不知道这两个格式之间有什么区别&#xff0c;更不知道在格式化时如何做出选择。本文将为大家介绍Mac选择FAT还是NTFS&#xff0c;并为大家推荐U盘和硬盘格式化两者选谁。 一、…

OpenCVHaar级联器实现人脸捕捉和微笑检测

概念 Haar 级联分类器是由多个简单分类器组成的复杂分类器&#xff0c;每个简单分类器都由 Haar 特征训练得到。Haar 级联器因其简单和快速而被应用于某些场景。OpenCV 提供多种预训练的 Haar 特征级联分类器&#xff0c;其已经在大量图像上进行了训练&#xff0c;并且针对特定…

【程序员写的诗】《悔思践》日期:2017-05-20 作者:橙 附:AI豆包点评和解释

悔思践 《悔思践》 日期&#xff1a;2017-05-20 作者&#xff1a;橙 问君心&#xff0c;愁几何。 望空杯&#xff0c;颜现愁。 苦衷苦&#xff0c;鸿志立。 乐中乐&#xff0c;断践行。 不践行&#xff0c;愁中悔。 悔中望&#xff0c;年已高。 鸿志行&#xff0c;行中思。 苦…

SH17:个人防护设备检测数据集(猫脸码客 第189期)

SH17 Dataset for PPE Detection 一、引言 在当今快速发展的工业社会中&#xff0c;工作场所事故仍频繁发生&#xff0c;对人类安全构成重大威胁&#xff0c;尤其是在建筑、制造等高风险行业中。为了有效减少这些事故带来的伤害&#xff0c;个人防护设备&#xff08;Personal…

不止于纸上谈兵,用代码案例分析如何确保RabbitMQ消息可靠性?

文章目录 文章导图可靠性分析-RabbitMQ 消息丢失的三种情况生产者发送可靠性消息实现2种方式1、采用事务消息事务消息投递方案设计1、本地库创建一个消息表(t_msg)2、事务消息投递的过程知识点拓展&#xff1a;Spring事务同步器 3、异常情况4、消息投递补偿job 核心代码讲解发送…

PyQt5-loading-圆环加载效果

效果预览 代码实现 from PyQt5.QtCore import QSize, pyqtProperty, QTimer, Qt, QThread, pyqtSignal from PyQt5.QtGui import QColor, QPainter from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QPushButton, QVBoxLayout, QLabel, QGridLayoutclass Cir…

2024ICPC网络赛1: C. Permutation Counting 4

题意&#xff1a; 给定 n n n个区间 [ L i , R i ] [L_i,R_i] [Li​,Ri​]设集合 A { { p i } ∣ p i 为排列&#xff0c; L i < p i < R i } A\{ \{ p_i\} | p_i为排列&#xff0c;Li<p_i<R_i\} A{{pi​}∣pi​为排列&#xff0c;Li<pi​<Ri​}&#xff…

Facebook直播限流是什么原因?是ip地址导致的吗

随着社交媒体和直播行业的蓬勃发展&#xff0c;Facebook直播已成为众多企业和个人进行品牌推广、产品展示和互动交流的重要平台。然而&#xff0c;在享受直播带来的便利与效益的同时&#xff0c;不少用户也面临着直播限流的困扰。本文将探讨Facebook直播限流的原因&#xff0c;…

京东App秒级百G日志传输存储架构设计与实战

本文作者&#xff1a;平台业务研发部-武伟峰&#xff0c;数据与智能部-李阳 背景 在日常工作中&#xff0c;我们通常需要存储一些日志&#xff0c;譬如用户请求的出入参、系统运行时打印的一些info、error之类的日志&#xff0c;从而对系统在运行时出现的问题有排查的依据。 …

8.1 溪降技术:横渡绳

目录 8.1 横渡绳将其置于上下文中&#xff1a;观看视频课程电子书&#xff1a;横渡绳一级横渡绳&#xff1a;识别使用横渡绳固定到横渡绳V7提示&#xff1a;保持张力中间点通过横渡绳上的中间点固定到锚点总结 8.1 横渡绳 绳上移动 横渡绳是一条水平安全绳&#xff0c;探险者可…

Leetcode—移除链表元素

题目描述 思路 创建新链表&#xff0c;将原链表中的值不为val的结点尾插到新链表中 画图解释 定义一个指针pcur去遍历原链表&#xff0c;创建一个空链表&#xff0c;newHead和newTail在初始情况指向空。 pcur遍历原链表不为val的结点尾插到新链表中 完整代码 /*** Definitio…

分治算法归并排序

分治算法 基本概念 把一个复杂的问题分成两个或更多的相同或相似的子问题&#xff0c;再把子问题分成更小的子问题…直到最后子问题可以简单的直接求解&#xff0c;原问题的解即子问题的解的合并。 分治法的基本步骤 分治法在每一层递归上都有三个步骤&#xff1a; step1分…

Linux内核(Kernel)启动过程分析

文章目录 Linux内核&#xff08;Kernel&#xff09;启动过程一、内核启动的基本流程1. 启动加载程序 (Bootloader)2. 内核解压阶段3. 内核启动&#xff08;Kernel Startup&#xff09;4. start_kernel函数5. 启动初始进程 二、内核文件加载及解压缩1.为什么是压缩文件2.文件类型…