数据结构和算法之十一:BitMap和布隆过滤器

数据结构之bitmap和布隆过滤器

bitmap

问题:100个数,取值范围在0-2亿,如何快速的判断一个数是否在这100个数中?

思路1:开一个数组,数值对应数组的下标,对存在的100个数进行标记,比如设置为1;这样,查找一个数是否存在时,直接通过数组下面获取对应的值,判断是否为1即可。

这个思路非常简单高效,就是有一个问题,因为取值范围0-2亿,开个两个亿的空间数组有点不大科学,而且如果内存有限制的话,还开不出来。

思路2:既然我只是对存在的数做一个标记,那么用一个二进制位就可以了吧,0表示不存在,1表示存在,那么一个int类型中,每个元素都可以表示32个数字,这样空间对比开int数组,直接缩小32倍;在判断一个数是否存在时,只需要找到这个数对一个这个位是0还是1就知道了。

这种解决方案用到的就是bitmap,底层其实就是位数组。

使用bitmap,其实主要的就是数值和下标的映射关系,比如申请一个int数组,一个int元素有32位长,那么size为10的int数组可以表示320个数。

其实对应到内存中,比如如下32个位,可表示0-31共32个数字。

0 0 0 0 0000 0000 0000 0000 0000 0000 0000

31,30,29,28…

对于int数组,数字n 的位置位于 int[n / 32]中的 n % 32 这个位上。

有了这些,我们就可以自己实现一个bitmap了(需要有位运算的知识):

/**
 * Bitmap
 *
 *  用位(bit)来表示一个数(元素)是否存在,相对于用boolean或者其他类型来表示一个元素是否存在,会节约大量的空间。
 *
 *  比如有100个数,取值范围在0-2亿,如何快速的判断一个数是否在这100个数中?
 *
 *  思路
 *  申请一个int数组,每一个数组元素有4个字节,也就是32个bit,用二进制来表示的话,如下
 *  0000 0000 0000 0000 0000 0000 0000 0000
 *  那么这样一个32个bit就可以表示32个数是否存在。
 *  比如
 *  0000 0000 0000 0000 0000 0000 0000 0000  表示0
 *  0000 0000 0000 0000 0000 0000 0000 0010  表示1
 *  0000 0000 0000 0000 0000 0000 0000 0100  表示2
 *  0000 0000 0000 0000 0000 0000 0000 1000  表示3
 *  以此类推,int[0]就可以表示0-31,int[1]就可以表示32-63 ....
 *  那么int[n]就可以表示n*32 到(n+1)*32-1 的数。
 *  回到前面的问题, 范围在0-2亿的数,我需要开辟的int数组大小为 2亿/32 + 1 。
 *
 *  映射关系, 数字n 的位置位于 int[n / 32]中的 n % 32 位上。
 *
 */
public class BitMap {
   

    private int max;
    private int[] bits;

    public BitMap(int max) {
   
        this.max = max;
        bits = new int[max / 32 + 1];
    }

    /**
     * 加入
     * @param n
     */
    public void add(int n){
   
        int index = n >> 5;  //定位到哪个 32 位的段上。
        int loc = n & (32 - 1) ; //定位32位段上的哪个位  n % 32 的另外一种写法
        bits[index] |= 1 << loc; //将loc的那个位置为1, 其他的位不变。
    }

    /**
     * 移除
     * @param n
     */
    public void remove(int n){
   
        int index = n >> 5;
        int loc = n & (32 - 1) ;
        bits[index] &= (1 << loc) - 1; 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值