位图+布隆过滤器+海量数据并查集(它们都是哈希的应用)

news2024/12/26 22:41:17

一)位图:

首先计算一下存储一下10亿个整形数据,需要多大内存呢,多少个G呢?

2^30=10亿,10亿个字节

byte kb mb gb

100000000个字节/1024/1024/1024=1G

所以10亿个字节就是1G,所以40亿个字节就是4G,也就是10个整形数据

给定40亿个不重复的无符号整数,没有排过序,给定一个无符号整数,如何可以快速地判断出一个数是否在这40亿个数中?

解法1:哈希表,10亿个字节,大概是1G,一个int型占4字节,10亿就是40亿字节很明显就是4GB,也就是如果完全读入内存需要占用4GB,40亿个整数是16G,一般运行内存存不下,所以说使用哈希表进行遍历时间复杂度是O(N)

解法2:排序+二分查找,O(N+logN),内存也是存不下的,二分查找必须是在内存中进行二分查找

解法3:位图,假设40亿个数据放到了40亿个比特位里面,2^32=40个亿,40亿除8等于X字节,X字节/1024=YKB,YKB/1024=ZMB=512M,1个位占用一个数据,所以仅仅使用512M内存就可以把这些数据全部存储起来,位图有的资料也称之为是bitMap

1)数据是否在给定的整形数据中恰好是在与不在,刚好是两种状态,那么此时就可以使用一个二进制比特位来代表数据是否存在的信息,如果二进制比特位为1,那么代表存在,为0表示不存在,比如说下面这个例子

2)array[index]/8确定的是在那一段区间

array[index]%8确定在那一段区间的哪一个位置

3)也可以很方便进行排序:从左到右输出二进制比特位是1的数据,但是有多个重复的数字就不好处理了,所以位图适用于整形况且没有重复的数据

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

5)位图天然是可以去重的,JAVA当中有一个类叫做BitMap,也叫做位图,也是JAVA.util的类,BitMap底层实现的是long[],但是我们所实现的是byte[]数组,是用于快速查找某一个元素是否存在,况且还可以节省空间;

import java.util.Arrays;

public class MyBitSet {
    public byte[] array;
    //每一个字节的比特位数都是从左到右边依次递增的
    public int usedSize;//记录在当前这个位图中存放了多少有效的数据
    public MyBitSet(){
        this.usedSize=0;
        this.array=new byte[1];
    }
    //这里面的n表示需要多少个比特位,有可能会多给1个字节,但是也是无所谓的
    public MyBitSet(int n){
        this.array=new byte[n/8+1];//假设n=12,此时实际上计算是1个字节,其实现在给2个字节也是可以的
        this.usedSize=0;
    }
    //设置某一位是1
    public void set(int val){
        if(val<0) throw new ArrayIndexOutOfBoundsException();
        int arrayIndex=val/8;//先找到这个数要放到第几个字节
        if(arrayIndex>array.length-1){
            //等于的时候刚刚好
          this.array= Arrays.copyOf(array,arrayIndex+1);
          //数组如果越界,那么直接进行扩容,假设存放130,那么计算的下标是16,那么扩容到17个个字节即可
        }
        int bitIndex=val%8;//再找到要修改这个字节的第几位
        //也就是说我们要把array[arrayIndex]的第bitIndex位设置成1
        this.array[arrayIndex]|=(1<<bitIndex);
        usedSize++;
    }
    //判断当前位是不是1
    public boolean get(int val){//判断当前val存储的这一位是1还是0
        if(val<0) throw new ArrayIndexOutOfBoundsException();
        int arrayIndex=val/8;
        if(arrayIndex>array.length-1) return false;
        int bitIndex=val%8;
        if(((array[arrayIndex]>>bitIndex)&1)==1) return true;//if((array[array[index]&(1<<bitIndex))!=0)
        return false;
    }
    //将val对应字节的存储对应位置置为0,就是相当于是在位图中删除这个值
    public void reset(int val){
        if(val<0) throw new ArrayIndexOutOfBoundsException();
        int arrayIndex=val/8;
        int bitIndex=val%8;
        usedSize--;
        array[arrayIndex]= (byte) ((~(1<<bitIndex))&array[arrayIndex]);
    }
    public int getUsedSize(){
        return usedSize;//返回当前位图中所存储的元素个数
    }
    //根据位图来进行排序

    public static void main(String[] args) {
        int[] nums={1,9,8,78,100,20,45,16};
        MyBitSet set=new MyBitSet(20);
        //1.现将所有的数字存放到位图里面
        for(int i=0;i<nums.length;i++){
            set.set(nums[i]);
            System.out.println(set.get(nums[i]));
        }
        System.out.println(set.getUsedSize());
        //2.从小到大遍历所有的字节,遍历到其中一个字节之后在进行按照下标从小到大遍历每一个字节里面的比特位
        for(int i=0;i<set.array.length;i++){
            for(int j=0;j<8;j++){
                if(((set.array[i])&(1<<j))!=0){
                    System.out.println(i*8+j);
                }
            }
        }
    }

}

二)布隆过滤器:哈希和位图的一个整合

布隆过滤器的提出:日常生活中在我们进行设计计算机软件的时候,通常要进行判断某一个元素是否在集合中,最直接的方法就是将所有的元素存储到一个哈希表中,当遇到一个新元素的时候,要进行判断当前这个元素是否出现在集合中

1)在布隆过滤器中最终并没有我所需要进行判断的值

2)布隆过滤器是一种比较巧妙的,紧凑型的概率性数据结构,特点是高效的插入和查询,可以用来告诉你某一样东西一定不存在或者是可能存在,它的原理是使用多个哈希函数,将一个数据映射到位图结构中,此种方式不仅仅可以提升查询效率,也是可以进行节省大量的内存空间,下面是类似与布隆过滤器的插入

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

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

相关文章

电脑重装系统之后设置

edge一直处于正在同步设置关闭系统自动更新更改默认安装路径 edge一直处于正在同步设置 解决办法&#xff1a;卸载重新安装 用电脑管家16可以卸载 电脑管家16 链接&#xff1a;https://pan.baidu.com/s/1f5T4uXrumL8Fne9hyvTHcg?pwd0122 提取码&#xff1a;0122 edge 链接&am…

Go Moonbeam:Ai智能写作助手

【产品介绍】 • 名称 Go Moonbeam • 具体描述 Moonbeam是一个人工智能驱动的长篇写作助手。你可以用它创建散文&#xff0c;故事&#xff0c;文章&#xff0c;博客&#xff0c;和其他长形式的内容&#xff0c;可以轻松的将混乱的笔记转换为大纲。同时它…

对象创建和内存分配

对象创建和内存分配 Java中类创建是在平常不过的操作了&#xff0c;但是一个类的创建到底经历 了哪些过程呢&#xff1f; 对象创建 创建方法 使用关键字new一个对象 使用反射机制 User user (User)Class.forName("xxx.xxx.User").newInstance(); User user Us…

Linux开发工具之编译器gcc/g++

gcc/g是编译代码的&#xff0c;gcc/g都可以编译c语言的代码&#xff0c;但是c的代码只能用g来编译 在linux中&#xff0c;只要我们对源文件用gcc/g进行编译&#xff0c;就会生成一个可执行程序a.out&#xff0c;然后我们执行该程序就可得到结果了&#xff0c;下面来细看一下gcc…

深入了解==和equals的区别

1. 浅说和equals的区别 &#xff08;1&#xff09;比较的类型 不一样 可以比较基础数据类型和引用类型&#xff0c;比较基础数据类型的数据时比较的是值&#xff0c;比较引用对象时比较的是引用的地址。 equals比较引用类型&#xff0c;默认比较的是两个引用对象的引用地址&a…

Acwing 3302. 表达式求值

Acwing 3302. 表达式求值 题目描述思路讲解代码展示 题目描述 思路讲解 代码展示 #include <iostream> #include <cstring> #include <algorithm> #include <stack> #include <unordered_map>using namespace std;stack<int> num; stack…

redis链接阻塞,导致程序没有响应

目录 一、场景二、原因三、排查1、使用 info client 命令查看redis链接统计情况2、使用 client list 命令查看redis链接信息3、关闭程序&#xff0c;看阻塞的链接是否有所减少4、排查使用 blpop 命令的相关代码 四、解决 一、场景 1、程序在运行一段时间后&#xff0c;会出现没…

【分布式】分布式ID

目录 前言一、雪花算法snowflake1. 组成2. 优缺点3. 时钟回拨怎么解决a. 时钟回拨b. 解决方案 4. 项目中如何使用 二、基于Redis三、基于Zookeeper四、号段模式五、指定步长的自增ID六、UUID参考 六、扩展总结 前言 分布式场景下&#xff0c;一张表可能分散到多个数据结点上。因…

【数据结构】C++实现二叉搜索树

二叉搜索树的概念 二叉搜索树又称为二叉排序树&#xff0c;它或者是一棵空树&#xff0c;或者是具有以下性质的二叉树&#xff1a; 若它的左子树不为空&#xff0c;则左子树上所有结点的值都小于根结点的值。若它的右子树不为空&#xff0c;则右子树上所有结点的值都大于根结…

问道管理:注册制对涨幅的限制?

注册制作为中国证券商场变革的重中之重&#xff0c;其本质是将发行商场转移到审阅商场&#xff0c;实现商场准入的有效管控。与此同时&#xff0c;注册制关于股票商场的涨幅也有必定的约束。 首先&#xff0c;注册制能够经过严厉的审阅来制约公司发行股票的数量和节奏。传统IP…

Linux 多线程( 进程VS线程 | 线程控制 )

文章目录 Linux进程 VS 线程进程的多个线程共享 进程和线程的关系线程创建 pthread_create获取线程ID pthread_self线程等待 pthread_join终止线程进程分离线程ID及进程地址空间布局 Linux进程 VS 线程 进程是资源分配的基本单位。线程是OS调度的基本单位。 线程共享进程数据…

Michael.W基于Foundry精读Openzeppelin第34期——MerkleProof.sol

Michael.W基于Foundry精读Openzeppelin第34期——MerkleProof.sol 0. 版本0.1 MerkleProof.sol 1. 目标合约2. 代码精读2.1 processProof(bytes32[] memory proof, bytes32 leaf) && processProofCalldata(bytes32[] calldata proof, bytes32 leaf)2.2 verify(bytes32[…

图像处理之频域滤波DFT

摘要&#xff1a;傅里叶变换可以将任何满足相应数学条件的信号转换为不同系数的简单正弦和余弦函数的和。图像信号也是一种信号&#xff0c;只不过是二维离散信号&#xff0c;通过傅里叶变换对图像进行变换可以图像存空域转换为频域进行更多的处理。本文主要简要描述傅里叶变换…

Heap及其应用

目录 堆的相关知识 什么是堆&#xff1f; 堆的性质&#xff1a; 堆的实现&#xff1a; 堆的结构&#xff1a; &#xff08;一&#xff09;堆的插入 向上调整法&#xff1a; 寻找父节点 循环结束条件 代码&#xff1a; &#xff08;二&#xff09;堆的删除 删除根节点…

Huggingface:免费开源AI人工智能API工具平台

| 【产品介绍】 • 名称 Huggingface • 成立/上线时间 2016年 • 具体描述 HuggingFace是一个开源的自然语言处理AI工具平台&#xff0c;它为NLP的开发者和研究者提供了一个简单、快速、高效、可靠的解决方案&#xff0c;让NLP变得更加简…

R绘制箱线图

代码大部分来自boxplot()函数的帮助文件&#xff0c;可以通过阅读帮助文件&#xff0c;调整代码中相应参数看下效果&#xff0c;进而可以理解相应的作用&#xff0c;帮助快速掌握barplot()函数的用法。 语法 Usage(来自帮助文件) barplot(height, ...)## Default S3 method: …

lua环境搭建数据类型

lua作为一门计算机语言&#xff0c;从语法角度个人感觉还是挺简洁的接下来我们从0开始学习lua语言。 1.首先我们需要下载lua开发工具包 在这里我们使用的工具是luadist 下载链接为&#xff1a;https://luadist.org/repository/下载后的压缩包解压后就能用。 2.接下来就是老生…

听GPT 讲Istio源代码--istioctl

在 Istio 项目的 istioctl 目录中&#xff0c;有一些子目录&#xff0c;每个目录都有不同的作用和功能。以下是这些子目录的详细介绍&#xff1a; /pkg: pkg 目录包含了 istioctl 工具的核心代码和库。这些代码和库提供了与 Istio 控制平面交互的功能&#xff0c;例如获取和修改…

postgresql 内核源码分析 btree索引插入分析,索引页面分裂流程,多举措进行并发优化,对异常进行保护处理

Btree索引插入流程分析 ​专栏内容&#xff1a; postgresql内核源码分析手写数据库toadb并发编程 ​开源贡献&#xff1a; toadb开源库 个人主页&#xff1a;我的主页 管理社区&#xff1a;开源数据库 座右铭&#xff1a;天行健&#xff0c;君子以自强不息&#xff1b;地势坤&a…

Swing程序设计详解(一)

【今日】 “若你决定灿烂&#xff0c;山无遮&#xff0c;海无拦” 目录 初识Swing 一 Swing简述 二 Swing常用窗体 2.1 JFrame窗体 2.2 JDialog对话框 2.3JOptionPane小型对话框 (1)通知框 (2)确认框 (3)输入框 (4)自定义对话框 三 常用布局管理器 3.1 绝…