位图算法与布隆过滤器

1.核心思想

1000000数字,如果使用散列表,则需要1000000*4字节大小的空间

如果使用二进制,从十进制映射到二进制,则需要10000000位bit 存储空间缩小了1/32

2.实现

int a[1+N/32]大小空间

0 -》0-31(十进制数)

1-》32-63

...

所以给定一个数N,先找到数组索引

index = N/32

找到数组下标以后,再找到该下标对应的位索引

由数学归纳法可知

index2 = N%32

很明显这不是二维数组。

因此我们需要优化一下,为了不影响已存储数字的影响,因此我们需要使用|,N&0x1F代表%,1<<代表小端存储,从右往左。

a[N>>32] |= 1<<(N&0x1F)

所以总结:

1.添加一个元素

addValue(N){

        index = N/32

        a[index] |= 1<<(N&0x1F)

}

2.查询一个元素

find(N){

        return a[N/32] & (1<<(N&0x1F)) != 1

}

缺点:

 1、当数据类似(1,1000,10万)只有3个数据的时候,用bitmap时间复杂度和空间复杂度相当大,只有当数据比较密集时才有优势。

2、如果数字的范围很大,数字范围不是1到1亿,而是1到10亿,那位图的大小就是10亿个二进制位,也就是120MB的大小,消耗的内存空间不降反增

怎么办?请布隆过滤器登场!

布隆过滤器就是为了解决刚刚这个问题,对位图这种数据结构的一种改进。

1、布隆过滤器的做法是,我们仍然使用一个1亿个二进制大小的位图,然后通过哈希函数,对数字进行处理,让它落在这1到1亿范围内。比如我们把哈希函数设计成f(x) = x%n。其中,x表示数字,n表示位图的大小(1亿),也就是,对数字跟位图的大小进行取模求余。

2、哈希函数会存在冲突的问题,为了降低冲突概率,可以设计一个复杂点、随机点的哈希函数。除此之外,还有其他方法吗?

3、我们来看布隆过滤器的处理方法。既然一个哈希函数可能会存在冲突,那用多个哈希函数一起定位一个数据,是否能降低冲突的概率呢?

4、使用 K 个哈希函数,对同一个数字进行求哈希值,那会得到K个不同的哈希值,我们分别记作X1,X2,X3,……Xk 。我们把这 K 个数字作为位图中的下标,将对应的BitMap[X1],BitMap[X2],BitMap[X3],……BitMap[Xk]都设置成true,也就是说,我们用 K 个二进制位,来表示一个数字的存在。

当我们要查询某个数字是否存在的时候,我们用同样的 K 个哈希函数,对这个数字求哈希值,分别得到Y1,Y2,Y3,……Yk 。看这 K 个哈希值,对应位图中的数值是否都为true,都是true,这个数字存在,任意一个不为true,说明这个数字不存在。

在这里插入图片描述

对于两个不同的数字,经过 K 个哈希函数处理之后,K 个哈希值都相同的概率就非常低了。尽管采用 K 个哈希函数之后,两个数字哈希冲突的概率降低了,但是,这种处理方式又带来了新的问题,那就是容易误判。看下面例子。

在这里插入图片描述 

布隆过滤器的误判有一个特点,那就是,它只会对存在的情况有误判。

如果某个数字经过布隆过滤器判断不存在,那说明这个数字真的不存在,不会误判

如果某个数字经过布隆过滤器判断存在,有可能误判,有可能并不存在。不过,只要我们调整哈希函数的个数、位图大小跟要存储数字的个数之间的比例,那就可以将这种误判的概率降到非常低。

尽管布隆过滤器会存在误判,但是,这并不影响它发挥大作用。很多场景对误判有一定的容忍度。
 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值