位图法
位图的基本概念是用一个位(bit)来标记某个数据的存放状态。
(这里没有限定整数的范围,所有把所有32位整数都考虑进去)的内存。接下去扫描着2.5亿个整数,查看位图中相对应的位,如果是00就变为01,如果是01就变为10,其他情况保持不变。扫描完成后仍为01的整数就是需要查找的数。
总结:
Bitmap适用于数据规模大,但数据状态少的情况。同时Bitmap在存在以下一些不足:
参考链接:https://blog.csdn.net/u013291394/article/details/50211181
位图其他应用:https://blog.csdn.net/wenqiang1208/article/details/76724338
布隆过滤器
然而Bitmap不是万能的,如果数据量大到一定程度,如开头写的64bit类型的数据,就不能用Bitmap。
所以Bitmap的好处在于空间复杂度不随原始集合内元素的个数增加而增加,而它的坏处也源于这一点——空间复杂度随集合内最大元素增大而线性增大。
Bloom Filter是一种空间效率很高的随机数据结构,它利用位数组很简洁地表示一个集合,并能判断一个元素是否属于这个集合。Bloom Filter的这种高效是有一定代价的:在判断一个元素是否属于某个集合时,有可能会把不属于这个集合的元素误认为属于这个集合(false positive)。因此,Bloom Filter不适合那些“零错误”的应用场合。而在能容忍低错误率的应用场合下,Bloom Filter通过极少的错误换取了存储空间的极大节省。
布隆过滤器需要的是一个位数组(和位图类似)和K个独立的映射函数(和Hash表类似)
直观的说,bloom算法类似一个hash set,用来判断某个元素(key)是否在某个集合中。
和一般的hash set不同的是,这个算法无需存储key的值,对于每个key,只需要k个比特位,每个存储一个标志,用来判断key是否在集合中。
算法:
1. 首先需要k个hash函数,每个函数可以把key散列成为1个整数
2. 初始化时,需要一个长度为n比特的数组,每个比特位初始化为0
3. 某个key加入集合时,用k个hash函数计算出k个散列值,并把数组中对应的比特位置为1
4. 判断某个key是否在集合时,用k个hash函数计算出k个散列值,并查询数组中对应的比特位,如果所有的比特位都是1,可能在集合中。如果不全为1,则一定不在集合中。
优点:
不需要存储key,节省空间
缺点:
1. 算法判断key在集合中时,有一定的概率key其实不在集合中
2. 无法删除
下图为K=3,哈希函数为X,Y,Z的情况:
误判补救方法是:再建立一个小的白名单,存储那些可能被误判的信息
应用:
网页URL的去重,垃圾邮件的判别,集合重复元素的判别,查询加速(比如基于key-value的存储系统)等。
主要工作是判断一条URL是否在现有的URL集合之中(可以认为这里的数据量级上亿)。
对于HTTP缓存服务器,当本地局域网中的PC发起一条HTTP请求时,缓存服务器会先查看一下这个URL是否已经存在于缓存之中,如果存在的话就没有必要去原始的服务器拉取数据了(为了简单起见,我们假设数据没有发生变化),这样既能节省流量,还能加快访问速度,以提高用户体验。
对于Web爬虫,要判断当前正在处理的网页是否已经处理过了,同样需要当前URL是否存在于已经处理过的URL列表之中。 每个URL都有其独特的指纹。虽然布隆过滤器还有极小的可能将一个没有抓取过的URL误判为已经抓取过,但它绝对不会对已经抓取过的URL进行重新抓取
假设邮件服务器通过发送方的邮件域或者IP地址对垃圾邮件进行过滤,那么就需要判断当前的邮件域或者IP地址是否处于黑名单之中。如果邮件服务器的通信邮件数量非常大(也可以认为数据量级上亿),那么也可以使用Bloom Filter算法。
在 leveldb 中有应用,提升查询未命中的效率。在从磁盘加载数据前,先从布隆过滤器中判断数据是否存在。如果不存在,就直接返回。这样可以减少磁盘访问,提升响应速度。
参考链接:https://www.cnblogs.com/liyulong1982/p/6013002.html
https://blog.csdn.net/wenqiang1208/article/details/76769001
https://www.cnblogs.com/cpselvis/p/6265825.html