10、Redis-位图(Bitmap)与计数位图(Counting Bitmap)以及布隆过滤器

1. 引言

位图(Bitmap)是一种高效的二进制数据结构,用于表示和操作大规模的集合数据。通过使用位数组(bit array),位图能够在非常小的内存空间内快速进行查找和存储操作。本文将详细介绍位图的基本概念、工作原理、应用场景,并进一步介绍如何扩展位图以支持计数功能,即计数位图(Counting Bitmap)。此外,还将结合 Redis 的布隆过滤器(Bloom Filter)来说明位图在实际应用中的使用。

2. 位图的基本概念

位图是一种数据结构,用一组二进制位来表示数据集合中的元素是否存在。每个位置上的位(bit)可以有两种状态:0 或 1。位图通过这些位来表示数据的存在与否。

示例

假设我们要表示一个集合 {0, 1, 3, 4, 6},可以用一个位图表示如下:

元素0123456
位图1101101

在这个位图中,1 表示元素存在,0 表示元素不存在。

3. 位图的工作原理

位图通过位数组实现,每个元素占用一个二进制位。位图的操作包括设置位(Set Bit)、清除位(Clear Bit)和检查位(Check Bit)。

设置位(Set Bit)

将位数组中的某一位置为 1,表示某个元素存在。例如,要将元素 5 插入集合,可以将位数组中第 5 位设为 1:

bitmap[5] = 1;

清除位(Clear Bit)

将位数组中的某一位置为 0,表示某个元素不存在。例如,要将元素 5 从集合中删除,可以将位数组中第 5 位设为 0:

bitmap[5] = 0;

检查位(Check Bit)

检查位数组中的某一位是否为 1,表示某个元素是否存在。例如,要检查元素 5 是否存在:

boolean exists = (bitmap[5] == 1);
4. 位图的图示解释

为了更好地理解位图的工作原理,我们通过图示来展示位图的各项操作。

图示 1:初始化位图

假设我们需要一个大小为 8 的位图,初始化时所有位都设置为 0。

索引:   0 1 2 3 4 5 6 7
位图:   0 0 0 0 0 0 0 0

图示 2:设置位

将第 2 位和第 5 位设置为 1,表示元素 2 和元素 5 存在。

操作: 设置第 2 位和第 5 位
索引:   0 1 2 3 4 5 6 7
位图:   0 0 1 0 0 1 0 0

图示 3:检查位

检查第 2 位和第 4 位,分别表示元素 2 和元素 4 是否存在。

操作: 检查第 2 位和第 4 位
索引:   0 1 2 3 4 5 6 7
位图:   0 0 1 0 0 1 0 0
结果: 第 2 位存在 (1), 第 4 位不存在 (0)

图示 4:清除位

将第 2 位清除为 0,表示元素 2 不存在。

操作: 清除第 2 位
索引:   0 1 2 3 4 5 6 7
位图:   0 0 0 0 0 1 0 0
5. 位图的优缺点

优点

  1. 空间效率高:每个元素只占用一个二进制位,非常节省内存。
  2. 查询速度快:通过简单的位操作,可以在常数时间内完成查找操作。
  3. 易于实现:位图的数据结构和操作都非常简单,易于实现和使用。

缺点

  1. 不适合稀疏数据:位图适合于数据密集的情况,对于稀疏数据,位图会浪费大量空间。
  2. 不支持删除操作:位图不支持删除操作,删除操作需要重新构建位图。
6. 位图的应用场景
  1. 快速查找:位图常用于快速查找场景,如判断一个元素是否存在于集合中。
  2. 去重操作:在数据处理中,位图可以高效地去除重复元素。
  3. 集合操作:位图可以用于集合的并集、交集和差集操作。
  4. 布隆过滤器:布隆过滤器使用多个位图和哈希函数实现高效的集合成员查询。
  5. 网络爬虫:用于判断 URL 是否已经被访问过,防止重复抓取。
7. 计数位图(Counting Bitmap)

计数位图(Counting Bitmap)是一种扩展的位图结构,不仅能表示元素是否存在,还能记录元素出现的次数。计数位图通过使用多个位来表示一个元素的计数值,而不是单个位。

计数位图的结构

计数位图的基本思想是用多个二进制位来表示一个元素的计数。例如,如果使用 4 位来表示计数,每个元素的计数范围是 0 到 15。以下是一个计数位图的示例:

元素0123456
位图0001001000000001001100000001

在这个示例中,每个元素用 4 位表示。位图表示元素 0 出现 1 次,元素 1 出现 2 次,元素 3 出现 1 次,元素 4 出现 3 次,元素 6 出现 1 次。

操作

  1. 设置计数

    将位数组中的某一位置为一个计数值,表示某个元素的计数。例如,要将元素 5 的计数设为 3:

    bitmap[5] = 3;
    
  2. 增加计数

    将位数组中的某一位置的计数增加。例如,要将元素 5 的计数增加 1:

    bitmap[5]++;
    
  3. 检查计数

    检查位数组中的某一位置的计数。例如,要检查元素 5 的计数:

    int count = bitmap[5];
    
8. 计数位图的图示解释

为了更好地理解计数位图的工作原理,我们通过图示来展示计数位图的各项操作。

图示 1:初始化计数位图

假设我们需要一个大小为 8 的计数位图,每个元素用 4 位表示计数,初始化时所有计数都设置为 0。

索引:   0    1    2    3    4    5    6    7
位图: 0000 0000 0000 0000 0000 0000 0000 0000

图示 2:设置计数

将第 2 个元素的计数设置为 1,第 5 个元素的计数设置为 3。

操作: 设置第 2 个元素的计数为 1,第 5 个元素的计数为 3
索引:   0    1    2    3    4    5    6    7
位图: 0000 0000 0001 0000 0000 0011 0000 0000

图示 3:增加计数

将第 2 个元素的计数增加 1,第 5 个元素的计数增加 2。

操作: 增加第 2 个元素的计数和第 5 个元素的计数
索引:   0    1    23    4    5    6    7
位图: 0000 0000 0010 0000 0000 0101 0000 0000

图示 4:检查计数

检查第 2 个元素和第 4 个元素的计数。

操作: 检查第 2 个元素和第 4 个元素的计数
索引:   0    1    2    3    4    5    6    7
位图: 0000 0000 0010 0000 0000 0101 0000 0000
结果: 第 2 个元素的计数为 2,第 4 个元素的计数为 0

图示 5:清除计数

将第 2 个元素的计数清除为 0。

操作: 清除第 2 个元素的计数
索引:   0    1    2    3    4    5    6    7
位图: 0000 0000 0000 0000 0000 0101 0000 0000
9. Redis 中的布隆过滤器

布隆过滤器(Bloom Filter)是一种基于位图的概率数据结构,主要用于集合成员查询。布隆过滤器通过多个哈希函数和位图,可以高效地判断一个元素是否在集合中。虽然存在一定的误判率,但布隆过滤器在很多场景下都非常实用。

布隆过滤器的原理

布隆过滤器由一个位数组和多个哈希函数组成。其工作原理如下:

  1. 初始化

    创建一个长度为 m 的位数组,初始时所有位都设为 0。选择 k 个独立的哈希函数,每个哈希函数将输入元素映射到 [0, m-1] 的范围内。

  2. 插入元素

    将元素插入布隆过滤器时,通过 k 个哈希函数对元素进行哈希,得到 k 个哈希值。根据每个哈希值,将位数组中对应位置的位设为 1。

  3. 查询元素

    查询元素是否在布隆过滤器中时,同样通过 k 个哈希函数对元素进行哈希,得到 k 个哈希值。检查位数组中对应位置的位是否都为 1。如果所有位置的位都是 1,则判断该元素可能在集合中;如果有一个位置的位为 0,则判断该元素一定不在集合中。

布隆过滤器的误判率

布隆过滤器的误判率与位数组长度 m、哈希函数数量 k 和插入元素数量 n 有关。误判率可以通过以下公式计算:

[ P = \left(1 - \left(1 - \frac{1}{m}\right){kn}\right)k ]

其中:

  • ( m ) 是位数组的长度。
  • ( k ) 是哈希函数的数量。
  • ( n ) 是插入元素的数量。
  • ( P ) 是误判率。

随着插入元素数量 ( n ) 增加,误判率 ( P ) 也会增加。可以通过增加位数组长度 ( m ) 或哈希函数数量 ( k ) 来降低误判率。

10. Redis 中的布隆过滤器操作命令

Redis 提供了布隆过滤器的实现,可以使用 Redis 提供的命令进行布隆过滤器的操作。Redis 布隆过滤器的实现基于 Redis 模块(RedisBloom),需要安装 RedisBloom 才能使用布隆过滤器功能。

常用命令

  1. BF.ADD

    向布隆过滤器添加元素。例如:

    BF.ADD mybloomfilter element1
    
  2. BF.MADD

    向布隆过滤器添加多个元素。例如:

    BF.MADD mybloomfilter element1 element2 element3
    
  3. BF.EXISTS

    检查元素是否在布隆过滤器中。例如:

    BF.EXISTS mybloomfilter element1
    
  4. BF.MEXISTS

    检查多个元素是否在布隆过滤器中。例如:

    BF.MEXISTS mybloomfilter element1 element2 element3
    

初始化布隆过滤器

可以使用 BF.RESERVE 命令初始化布隆过滤器,指定位数组长度和误判率。例如:

BF.RESERVE mybloomfilter 0.01 1000

此命令创建一个布隆过滤器 mybloomfilter,误判率为 1%,容量为 1000 个元素。

11. 总结

位图是一种高效的二进制数据结构,通过使用位数组来表示数据集合中的元素是否存在。计数位图是位图的一种扩展,能够记录元素的出现次数。布隆过滤器则通过多个哈希函数和位图实现高效的集合成员查询。位图、计数位图和布隆过滤器在存储和查询方面具有极高的空间效率和查询速度,适用于快速查找、去重、计数和集合操作等场景。通过本文的详细介绍和图示解释,读者可以深入理解这些数据结构和它们在 Redis 中的实际应用。希望本文能帮助读者在实际项目中更好地应用这些高效的数据结构。

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

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

相关文章

详细分析Sql中SELECT TOP的基本知识

目录 前言1. 基本知识2. 彩蛋 前言 在Sql server中查询比较消费占用空间,对此需要从子句中从结果集中选择前面的若干行 在不同的数据库系统中,这个功能的实现方式略有不同 1. 基本知识 Microsoft SQL Server 使用 TOP 关键字来限制返回的行数 SELEC…

生物墨水:3D组织生物打印的基石

生物墨水是3D组织生物打印技术的核心组成部分。生物墨水通常由生物材料(如水凝胶聚合物)与所需的细胞和/或其他生物大分子(例如生长因子)混合而成。为了成功地进行组织生物打印,生物墨水必须满足以下要求: …

为什么要设计DTO类

为什么要使用DTO类,下面以新增员工接口为例来介绍。 新增员工 1.1 需求分析和设计 1.1.1 产品原型 一般在做需求分析时,往往都是对照着产品原型进行分析,因为产品原型比较直观,便于我们理解业务。 后台系统中可以管理员工信息…

Bug记录:【com.fasterxml.jackson.databind.exc.InvalidDefinitionException】

bug记录 序列化错误 异常com.fasterxml.jackson.databind.exc.InvalidDefinitionException: 完整错误(主要是FAIL_ON_EMPTY_BEANS) 00:15:20.250 [http-nio-3000-exec-1] ERROR org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].[dispatcherServlet] - S…

数据驱动的内容优化:Kompas.ai如何提升内容表现

在数字化营销时代,内容是企业与用户沟通的重要桥梁。然而,随着信息量的爆炸性增长,如何让内容在激烈的竞争中脱颖而出,成为每个营销人员面临的问题。数据驱动的内容优化策略,通过精准分析和科学决策,帮助品…

线程安全(一)Java锁(锁分类、锁升级、锁优化)

目录 一、乐观锁二、悲观锁三、自旋锁3.1 自旋锁的优缺点:3.2 自旋锁的时间阈值:3.3 自旋锁的开启:四、Synchronized 同步锁4.1 Synchronized 作用范围:4.2 Synchronized 核心组件:4.3 Synchronized 实现:4.4 Synchronize 补充:五、ReentractLock 锁5.1 Lock 接口的主要…

解码特征的力量:SKlearn中特征重要性评估全攻略

解码特征的力量:SKlearn中特征重要性评估全攻略 在机器学习模型的开发过程中,理解各个特征对预测结果的贡献度是至关重要的。特征重要性评估不仅可以帮助我们识别最有影响力的特征,还可以用于模型解释和简化。Scikit-learn(简称s…

业务发展中 10 个最佳的 OKR 示例

业务发展是推动组织增长、培养合作伙伴关系和扩大市场覆盖范围的重要职能。目标和关键结果 (OKR) 可以作为推动业务发展工作和实现战略目标的强大工具。在这里,我们展示了业务发展中的十个最佳 OKR 示例,为旨在在该领域脱颖而出并实现其增长目标的组织提…

抓包工具Wireshark

一、Wireshark介绍 Wireshark(前称Ethereal)是一款免费的开源网络封包分析软件,用于截取和显示网络封包的详细信息。它通过WinPCAP接口直接与网卡进行数据报文交换,适用于网络管理员、网络安全工程师、开发者等专业人士使用。作为…

产品体验周刊第2期(2024-7-8)

产品体验 阿里系产品的营销活动 无论是支付宝,饿了么,咸鱼等,产品的营销活动频次过高,且几乎任何一个活动页都让人无法理解想要表达什么,只有满屏的红包、优惠等字眼,开始对这类活动脱敏也是基于这些产品…

Redis事件和整体框架

Redis服务器是事件驱动程序,主要处理两类: 文件事件 时间事件 文件事件 基于Reactor模式使用IO多路复用来监听多个套接字,并且根据套接字的事件分配相应的事件处理器。 IO多路事件都会放在一个队列中,并发时,有序执行…

在pycharm中使用jupyter

在pycharm中使用jupyter 前置条件:你的环境中应该有juptyer ,没有的话 pip install jupyter 点击项目目录,右键->new->jupyter notebook 打开file settings 找到 jupyter server (按照默认的用代理服务器就行) P…

大连外贸建站公司wordpress主题模板

Robonaut萝卜纳特WP外贸站模板 适合用于工业机器人公司出口做外贸搭建公司官方网站使用的WordPress模板。 https://www.jianzhanpress.com/?p7091 优衣裳WordPress外贸建站模板 简洁的wordpress外贸独立站模板,适合服装、衣服、制衣外贸公司搭建公司官方网站使用…

python- Flask模块 demo

文章目录 前言python- Flask模块 demo1. 主要特点2. demo 准备工作3. demo 实例4. 测试 前言 如果您觉得有用的话,记得给博主点个赞,评论,收藏一键三连啊,写作不易啊^ _ ^。   而且听说点赞的人每天的运气都不会太差&#xff0c…

前端JS特效第21集:HTML5响应式多种切换效果轮播大图切换js特效代码

HTML5响应式多种切换效果轮播大图切换js特效代码&#xff0c;先来看看效果&#xff1a; 部分核心的代码如下(全部代码在文章末尾)&#xff1a; <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-t…

分别通过LS和RML进行模型参数辨识matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 4.1 最小二乘法(LS)参数辨识 4.2 递归最大似然估计(RML)参数辨识 5.完整程序 1.程序功能描述 分别通过LS和RML进行模型参数辨识matlab仿真&#xff0c;仿真输出参数辨识的误差&#xff0c…

Qt坐标变换详解

文章目录 Qt坐标变换详解初始化 QPainter设置画笔和字体坐标平移坐标旋转坐标扭转坐标缩放保存和恢复坐标状态复位所有的坐标变换综合示例&#xff1a;绘制五角星解释 总结 Qt坐标变换详解 在图形编程中&#xff0c;坐标变换是非常重要的概念&#xff0c;它可以帮助我们方便地…

InvalidVersionSpecError: Invalid version spec: =2.7解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

MATLAB神经网络中的seq2con()

seq2con 源文档解释&#xff1a;Convert sequential vectors to concurrent vectors 源文档例1&#xff1a; p1 {1 4 2} p2 seq2con(p1) 结果&#xff1a; p1 13 cell 数组 {[1]} {[4]} {[2]} p2 11 cell 数组 {13 double} {[1,4,2]} 源文档例2&#xff1a; p…

接口分组:内部调用与第三方调用接口

一套微服务项目&#xff0c;给本项目前端调用的接口和给其他第三方调用的接口&#xff0c;是否应该拆分成两个不同的服务&#xff08;或网关&#xff09;&#xff0c;还是可以放在一个服务中&#xff1f; 对于一套微服务项目&#xff0c;将给前端调用的接口与给第三方调用的接…