高阶数据结构----布隆过滤器和位图

(一)位图

  位图是用来存放某种状态的,因为一个bit上只能存0和1所以一般只有两种状态的情况下适合用位图,所以非常适合判断数据在或者不在,而且位图十分节省空间,很适合于海量数据,且容易存储,数据无重复的场景(因为位图是天然去重的)

 那我们来看一下他是如何节省空间的

我们看这个例子,如果我们不使用位图,一共10个整型数据,需要消耗40个字节,但是如果使用位图,我们就只需要3个字节就可以判断这个数字是否存在

注:10亿字节1个g

(二)位图的实现及作用

public class bitmap {
    public byte[] elem;
    public int usedSize;
    public bitmap() {
        elem=new byte[1];
    }
    //初始化位图长度
    public bitmap(int n) {
        elem=new byte[(n/8)+1];
    }
    public void setElem(int val){
        //找到插入第几个byte中   val/8
        if (val<0)throw new IndexOutOfBoundsException();
        int arrIndex=val/8;
        //找到插入到byte的第几个bit中 val%8
        int bitIndex=val%8;
        elem[arrIndex] |= (1<<bitIndex); //这里用| 之前为1的就一直为1,当前我要插入的一定会修改为1
        usedSize++;  //这里其实不一定正确,因为如果本身就存在这个元素,那么我们不应该++
    }
    public boolean get(int val){
        //找到插入第几个byte中   val/8
        if (val<0)throw new IndexOutOfBoundsException();
        int arrIndex=val/8;
        //找到插入到byte的第几个bit中 val%8
        int bitIndex=val%8;
        if((elem[arrIndex] & 1<<bitIndex)!=0){   //这里是用& 把其余所有位都变成0,如果当前我要找的存在就不为0
            return true;
        }
        return false;
    }
    public void delete(int val){
        //找到删除第几个byte中   val/8
        if (val<0)throw new IndexOutOfBoundsException();
        int arrIndex=val/8;
        //找到删除到byte的第几个bit中 val%8
        int bitIndex=val%8;
        elem[arrIndex] &=~(1<<bitIndex);
        usedSize--;
    }
}

我们之后来看一下我们的set delete和get方法中的不同点

我们发现只有对bit位的处理是不同的,找位置的代码都是一样的,所以我们就来看对bit位的处理

首先是set方法,我们是用了 | 只要有1就为1 这样是为了确保在我们添加元素的时候不影响其他bit位上的元素,如果我们变成& 就会这样

我们发现下标为5的元素被修改为0了,这显然是不对的,如果是异或那就更不对了

然后我们来看get 我们用了 & 只有都为1的时候才为1,其他都是0,也就是说我们想找这个元素,且他存在的时候才为1,其他都为0,如果使用 | 我们就无法判断了

最后一个我们看delete 我们先取反然后再& ,这样能够保证只有这一位是0,其他位全为1,如果其他位本身不存在那么1&0还是0,如果存在1&1为1还是存在,而我们要删除的位,无论如何都为0,这里可能要问,为什么不能使用异或,异或有一个情况会发生错误,如果我们删除的位置本身不存在为0,那么就会导致0^1为1,反倒存在了,所以不可以用^

 我们可以使用我们的位图进行排序

 public static void main(String[] args) {
        int[] array = {1,3,2,13,10,3,14,18,3};
        final bitmap bitSet = new bitmap(18);
        for (int tmp:array
             ) {
            bitSet.setElem(tmp);
        }
        for (int i = 0; i < bitSet.elem.length; i++) {
            for (int j = 0; j < 8; j++) {
                if((bitSet.elem[i] & (1 << j) ) != 0 ) {
                    System.out.println(i*8+j);
                }
            }
        }
    }

其实位图我们Java也给我们实现过了

但是他的底层是long类型的数组 而我们是byte类型的

那我们来总结一下位图的应用

1.快速查找某个数据(适合处理整数)是否在集合中

2.排序+去重

3.求两个集合的交集,并集

(三)布隆过滤器

  我们上面说的位图,适合存储整数,如果是对象,那我们要存到那一个byte位?所以我们就出现了布隆过滤器

  布隆过滤器是哈希和位图思想的结合

之前我们有一篇博客讲了布隆过滤器解决缓存穿透的问题 我们说布隆过滤器用于一些可以存在误判率的场景下,因为布隆过滤器是通过多个哈希函数多次将数据给存放到位图上

像这样

但是因为我们在多次插入后可能会出现这种场景

我们发现不同数据hash后可能会落到同一个格子,但是还好这个还有一位不同,更极端点的例子

一个数据多次hash,都落到了1位置上,这样就会判断它存在,但是它实际上是不存在的,此时就会出现误判

 所以布隆过滤器对于结果来说,存在不一定存在,不存在一定不存在

布隆过滤器的优缺点:

优点:

1.增加和查询元素的时间复杂度为O(1)

2.布隆过滤器不存元素本身,所以适合要保密的场景

3.布隆过滤器由于使用了位图,很节省空间

4.数据量很大时,布隆过滤器可以表示全集(也就是能表示更多的元素)

5.适用相同hash函数的布隆过滤器可以进行交,并,差运算

缺点:

1.存在一定误判率

2.不能获取元素本身(hash不可逆)

3.一般不能删除元素(因为多个元素可能hash到一个位置上)

4.这样删除会存在计数回绕问题

总结下布隆过滤器:适合一些非整数的数据,通过hash+位图的思想,查找的时间复杂度和hash函数个数有关但都是常数,也不会太大,存储的不是信息本身只能判断数据是否存在,但是有误判率

(四)海量数据面试题

1.给定100亿个整数,设计找到值出现一次的整数

解法一:哈希切割

  我们把这100亿个整数哈希到不同小文件中,这样相同的数字是会在一起的,然后遍历每个小文件,记录只出现一次的整数到另一个文件中,这样就能判断那个数字只出现一次

解法二:位图

 我们把这100亿个整数放到两个位图中

我们适用二进制计数的方式,这样只出现一次的整数就是0 1,然后我们遍历整个位图就可以得到了。

 当然也可以只用一个位图,那就是两个bit位存一个数据

这样我们需要/4和%4找位置了

2.给定两个文件分别有100亿个整数,但是我们只有1g内存,如何找到两个文件交集

解法一:哈希切割

我们依然将两个文件分别hash成多个小文件,这样相同的数据大概率在同一个文件中,然后我们求这两个文件的交集放到另一个文件中

解法二:位图

我们将第一个文件的数据放到位图中,然后遍历第二个文件,如果在位图中存在了,那么就是两个文件的交集

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

 注意我们这题是query,那就说明不是整数,那就不适合用位图,但是我们可以适用布隆过滤器

解法一:哈希切割(精确算法)

我们依然将两个文件分别hash成多个小文件,这样相同的数据大概率在同一个文件中,然后我们求这两个文件的交集放到另一个文件中(跟上面一样)

解法二:近似算法

把第一个文件的query映射到布隆过滤器中,然后读第二个文件,把每个query都放到布隆过滤器查找(有误判率)所以是近似算法

那我们来总结一下:哈希切割是比较通用的方法,通过hash函数把相同的数据都放到一个文件中,然后进行判断和处理

位图适合整型数据的处理,而布隆过滤器是适合允许有一定误报率的处理

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

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

相关文章

Leetcode 最大正方形

java 实现 class Solution {public int maximalSquare(char[][] matrix) {//处理特殊情况if(matrix null || matrix.length 0 || matrix[0].length 0) return 0;int rows matrix.length;int cols matrix[0].length;int[][] dp new int[rows][cols]; //dp[i][j]的含义是以…

Redis--缓存穿透、击穿、雪崩以及预热问题(面试高频问题!)

缓存穿透、击穿、雪崩以及预热问题 如何解决缓存穿透&#xff1f;方案一&#xff1a;缓存空对象方案二&#xff1a;布隆过滤器什么是布隆过滤器&#xff1f;优缺点 方案三&#xff1a;接口限流 如何解决缓存击穿问题&#xff1f;方案一&#xff1a;分布式锁方案一改进成双重判定…

嵌入式 Linux LED 驱动开发实验

一、Linux 下 LED 灯驱动原理 a)地址映射 在编写驱动之前,我们需要先简单了解一下 MMU 这个神器, MMU 全称叫做 Memory Manage Unit,也就是内存管理单元。在老版本的 Linux 中要求处理器必须有 MMU,但是现在 Linux 内核已经支持无 MMU 的处理器了。 MMU 主要完成的功能如…

网络安全:交换机技术

单播&#xff0c;组播广播 单播(unicast): 是指封包在计算机网络的传输中&#xff0c;目的地址为单一目标的一种传输方式。它是现今网络应用最为广泛&#xff0c;通常所使用的网络协议或服务大多采用单播传输&#xff0c;例如一切基于TCP的协议。组播(multicast): 也叫多播&am…

C# 在PDF中添加和删除水印注释 (Watermark Annotation)

目录 使用工具 C# 在PDF文档中添加水印注释 C# 在PDF文档中删除水印注释 PDF中的水印注释是一种独特的注释类型&#xff0c;它通常以透明的文本或图片形式叠加在页面内容之上&#xff0c;为文档添加标识或信息提示。与传统的静态水印不同&#xff0c;水印注释并不会永久嵌入…

fpga系列 HDL:verilog 常见错误与注意事项 位宽不匹配+case 语句中没有覆盖所有情况

位宽不匹配问题 信号或操作数的位宽不匹配&#xff0c;可能导致仿真或综合错误。 module top (input wire [3:0] a,output wire [7:0] b );assign b a; endmodulecase 语句中没有覆盖所有情况 module top (input wire [1:0] sel,input wire [7:0] a,input wire [7:0] b,in…

groupby 操作的不同参数

groupby 是数据分析中一个非常强大的操作&#xff0c;可以根据指定的规则将数据拆分成多个组&#xff0c;并对每个组进行聚合、转换或过滤等操作。我们逐个解释这些参数的作用&#xff0c;并通过数值举例进行说明。 参数解释 by&#xff1a;分组依据 by 参数指定了分组的依据&…

鸢尾花种类预测--数据集介绍

1.6 案例&#xff1a;鸢尾花种类预测--数据集介绍 学习目标 目标 知道sklearn中获取数据集的方法知道sklearn中对数据集的划分方法 本实验介绍了使用Python进行机器学习的一些基本概念。 在本案例中&#xff0c;将使用K-Nearest Neighbor&#xff08;KNN&#xff09;算法对鸢尾…

基于深度学习的视觉检测小项目(二) 环境和框架搭建

一、环境和框架要求 SAM的环境要求&#xff1a; Python>3.7 PyTorch>1.7 torchvision>0.8 YOLO V8的环境要求&#xff1a;YOLO集成在ultralytics库中&#xff0c;ultralytics库的环境要求&#xff1a; Python>3.7 PyTorch>1.10.0 1、确定pytorch版本…

Javascript算法——回溯算法(组合问题)

相关资料来自《代码随想录》&#xff0c;版权归原作者所有&#xff0c;只是学习记录 回溯 回溯模板 void backtracking(参数) {if (终止条件) {存放结果;return;}for (选择&#xff1a;本层集合中元素&#xff08;树中节点孩子的数量就是集合的大小&#xff09;) {处理节点…

Java Excel转PDF POI+Itext5

由于现在存在需求&#xff0c;通过Java将数据文本生成特点格式Excel&#xff0c;再输出为PDF。 调研了一些方案&#xff0c;最终决定使用POI写入Excel,再使用Itext5生成PDF。 在网上找了一些Itext的转换工具类&#xff0c;进行了一些改动。 目前市面上 Excel 转 PDF 的组件…

linux nginx maccms管理后台无法进入页面不存在和验证码不显示的问题

windows中运行maccms非常顺利&#xff0c;轻松搭建了。并一切正常。而我在linux中搭建缺遇到了一个非常奇怪的问题。进入管理后台&#xff0c;明明"admin.php"(比如重命名成a.php)的页面是存在的&#xff0c;访问时缺提示页面不存在&#xff01;稍后就自动跳到首页了…

C# 服务调用RFC函数获取物料信息,并输出生成Excel文件

这个例子是C#服务调用RFC函数&#xff0c;获取物料的信息&#xff0c;并生成Excel文件 上接文章&#xff1a;C#服务 文章目录 创建函数创建结构编写源代码创建批处理文件运行结果-成功部署服务器C#代码配置文件注意&#xff01;&#xff01; 创建函数 创建结构 编写源代码 创建…

在 SQL 中,区分 聚合列 和 非聚合列(nonaggregated column)

文章目录 1. 什么是聚合列&#xff1f;2. 什么是非聚合列&#xff1f;3. 在 GROUP BY 查询中的非聚合列问题示例解决方案 4. 为什么 only_full_group_by 要求非聚合列出现在 GROUP BY 中&#xff1f;5. 如何判断一个列是聚合列还是非聚合列&#xff1f;6. 总结 在 SQL 中&#…

Postman测试big-event

报错500。看弹幕&#xff0c;知道可能是yml或sql有问题。 所以检查idea工作台&#xff0c; 直接找UserMapper检查&#xff0c;发现完全OK。 顺着这个error发现可能是sql有问题。因为提示是sql问题&#xff0c;而且是有now()的那个sql。 之后通过给的课件&#xff0c;复制课件…

SpringBoot 2.6 集成es 7.17

引言 在现代应用开发中&#xff0c;Elasticsearch作为一个强大的搜索引擎和分析引擎&#xff0c;已经成为许多项目不可或缺的一部分。Spring Boot作为Java生态中最受欢迎的微服务框架之一&#xff0c;其对Elasticsearch的支持自然也是开发者关注的焦点。本文将详细介绍如何在S…

沙箱模拟支付宝支付3--支付的实现

1 支付流程实现 演示案例 主要参考程序员青戈的视频【支付宝沙箱支付快速集成版】支付宝沙箱支付快速集成版_哔哩哔哩_bilibili 对应的源码在 alipay-demo: 使用支付宝沙箱实现支付功能 - Gitee.com 以下是完整的实现步骤 1.首先导入相关的依赖 <?xml version"1…

自行下载foremos命令

文章目录 问题描述其他小伙伴的成功解决方案&#xff0c;但对我不适用解决思路失败告终 最终解决成功解决思路解决步骤 问题描述 在kali系统终端中输入foremost&#xff0c;显示无此命令 其他小伙伴的成功解决方案&#xff0c;但对我不适用 解决思路 正常来说使用命令 apt-g…

商米电子秤服务插件

概述 SunmiScaleUTS封装商米电子秤服务模块&#xff0c;支持商米旗下S2, S2CC, S2L CC等设备&#xff0c;设备应用于超市、菜市场、水果店等,用于测量商品的重量,帮助实现快捷、准确、公正的交易等一系列商业场景。 功能说明 SDK插件下载 一. 电子秤参数 型号:S2, S2CC, …

快速将索尼手机联系人导出为 HTML 文件

我想将 Sony Xperia 手机上的联系人导出到计算机上进行备份&#xff0c;并在需要时进行编辑。这可以做到吗&#xff1f;如何做到&#xff1f;作为助手我需要下载什么工具吗&#xff1f; 当您的 Android 手机上存储了如此多的重要联系人&#xff0c;而您又不想丢失它们时&#…