数据结构学习:位图及布隆过滤器

一、位图概念

1、可以先了解下位运算
位运算
2、位图就是充分利用位运算,来进行数据的查找、去重
比如有一千万个数,范围为一到一亿,如果判断某个整数是否在其中,应该怎么做呢?

  • 很显然,我们可以申请一个大小为一亿,数据类型为boolean的数组,把这一千万个数放在数组中,标志位为True。比如K这个数在其中,array(k)= true;判断某个数是否在其中,只需判断返回是否为true即可;
  • 不过,很多语言中boolean大多占用1个字节,用true/false表示存不存在,并不能节省太多内存空间;
  • 这时候就可以利用bit的特性,我们知道1个字节占用8个bit位,如果把这一亿个数全放在bit位中,存在就设置为1,不存在就设置为0;相当于1个字节可以表示8个数字;比如6可以表示成00000100
  • 至于如何放在bit位中,不好描述清楚,请看代码实现

二、代码实现

public class BitMap { // Java中char类型占16bit,也即是2个字节
    private char[] bytes;
    private int nbits;

    public BitMap(int nbits) {
        this.nbits = nbits;
        this.bytes = new char[nbits/16+1];
    }

    /*
        把int所在的bit位置为1
     */
    public void set(int k) {
        if (k > nbits) return;
        int byteIndex = k / 16;
        int bitIndex = k % 16;
        bytes[byteIndex] |= (1 << bitIndex);
    }

    /*
        两个bit位进行与操作,若为1,表示两个bit都为1,即这个数字已经存在
     */
    public boolean get(int k) {
        if (k > nbits) return false;
        int byteIndex = k / 16;
        int bitIndex = k % 16;
        return (bytes[byteIndex] & (1 << bitIndex)) != 0;
    }
}

三、位图的优势

  • 每个数字用一个二进制位表示,占用空间非常小,相当于以前一个int(4字节),现在能表示32个数
  • 计算机本身是使用位运算的,使用位图的话可以充分利用这个特点,计算效率高

四、布隆过滤器

  1. 假设还是有1千万个数,数字的范围为1到10亿,数字范围比之前增大了10倍,即使用位图也会消耗不少的内存空间,这时候布隆过滤器就出场了,布隆过滤器还是使用1亿个bit位,只不过是对这1千万个数字进行哈希,比如哈希取模,f(x)
    = y % n,n就是1亿,就可以保证1到10亿都落在这1亿个bit位中
  2. 但这种会有个问题,比如一和一亿零一同样进行哈希取模,都是落在1这个bit位,那么就无法判断存储的是一还是一亿零一
  3. 针对这种情况,可以使用多个哈希函数去定位一个数据,是否可以降低冲突的概率呢?答案是可以的,比如x经过三次哈希之后,在bit位1、3、9为true;y经过三次哈希之后,在bit位2、4、8为true。但这样又会带来一个新的问题,比如z经过三次哈希之后为1、3、8,而138的bit位又都为true,这就容易出现误判的情况,针对这种误判,只能尽可能提高位数组的长度并且使用尽可能多的哈希函数,但这也会带来存储空间的提升和性能的下降,因此这需要权衡
  4. 对于某个数据,如果经过了布隆过滤器判断不存在,那么它一定不存在;若判断存在,那是有可能存在,因此布隆过滤器适用于对误判容忍度比较高的场景

应用场景:
1、缓存穿透:当key对应的数据在数据源中并不存在,
2、爬虫网址去重
3、黑名单:不在黑名单数据,会被布隆过滤器过滤出来;可能存在的网址再去数据源查询,降低数据源压力

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我爱夜来香A

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值