赞
踩
上面这个链接对布隆过滤器进行了比较详细的介绍,可以仔细看一看。在这里,我自己主要写一写自己的理解,并用代码实现一个简单的版本。
BloomFilter往往用于数据量太大内存一下子存不了的情况,其实本质有点类似bit-map 的扩展,它的原理:
当一个元素被加入集合时,通过 K 个 Hash 函数将这个元素映射成一个位阵列(Bit array)中的 K 个点,把它们置为 1。检索时,我们只要看看这些点是不是都是 1 就(大约)知道集合中有没有它了:
如果这些点有任何一个 0,则被检索元素一定不在;
如果都是 1,则被检索元素很可能在。
我们举一个例子,比如当我们想要爬虫一个很大的网页,每个网页又包含了很多很多网页,我们需要爬取这上面的信息。为了防止重复爬取某些网页,我们需要把已爬取的网页存在一个集合中,每次遇到一个网页和这个集合比较确定是否要爬取。
网页url(如www.baidu.com)可以看作是一个比较长的字符串string,如果直接保存string显然太浪费空间了。
为此我们可以利用哈希函数,将每个url通过哈希映射为一个值,将这个值保存起来,我们只需要到时候看这个值在不在就可以判定这个url是否存在。由于只需要知道在或者不在这两种状态,使用位图能够极大的帮我们节省空间。
根据上面所说,布隆过滤器的查询效率和空间效率会很高,这是因为它结合了位图和哈希函数的优点。
俗话说,人无完人,布隆过滤器的优点很棒,但是它也有着它的缺陷,那就是哈希函数自带的哈希冲突。我们知道没有任何哈希函数能够避免冲突,布隆也是一样。
以上面的url为例,我们首先需要将一个url映射为一个整数n,(url)往往都是很长的字符串,根据常规的除留余数法,根据n % k将对应的bit位置1,表示这个字符串存在。在这里,有一个问题,字符串很长的情况下以及字符串很多的情况,必然会出现n % k的值重复,也就是说假如有两个string a,string b通过上面计算都将n % k对应的比特位置1,那么就无法判定某个字符串是否真的存在了。
这也就是布隆过滤器的一个缺点:误判。在上面的例子中,假设a已经将对应的bit位置1,此时就算b没有出现,但是由于a,b对应的比特位都一样是1,会误以为b存在,这就是所谓的误判。
为了减小误判率,我们可以设置多个hash函数,比如让一个string a映射到多个bit位上,只有当这些bit位都为1才能判定这个字符串a存在。这样以来误判率就减小了很多,虽然还是有可能误判。比如
如上图,由于之前a,b映射已经让c对应的600/1000位都为1了,那么就算c不存在,我们也会根据比特位来判定它存在,因此判定存在是不准确的(当然多个hash让这个误判几率变的很小)。但是如果判定不存在是准确的,因此只有当一个string通过hash映射的所有比特位为1才能判定存在性。这也就是之前的布隆原理。
当一个元素被加入集合时,通过 K 个 Hash 函数将这个元素映射成一个位阵列(Bit array)中的 K 个点,把它们置为 1。检索时,我们只要看看这些点是不是都是 1 就(大约)知道集合中有没有它了:
如果这些点有任何一个 0,则被检索元素一定不在;
如果都是 1,则被检索元素很可能在。
下面我们给出它的实现代码:
它的底层是一个bitmap:(关于bitmap可见我的另一篇博客BitMap)
#include "BitMap.h"
#include "HashFun.h"
// simple BloomFilter for string
class BloomFilter
{
public:
BloomFilter(size_t num) //the num of string to be inserted
: _bm(num * 5 * 2) // each string has five hashfun corresponding to 5 bit
, _size(num * 5 * 2)
{}
void Insert(const string& key)
{
size_t hash1 = HashFun1()(key) % _size;
size_t hash2 = HashFun2()(key) % _size;
size_t hash3 = HashFun3()(key) % _size;
size_t hash4 = HashFun4()(key) % _size;
size_t hash5 = HashFun5()(key) % _size;
_bm.Set(hash1);
_bm.Set(hash2);
_bm.Set(hash3);
_bm.Set(hash4);
_bm.Set(hash5);
}
bool HasExisted(const string& key)
{
size_t hash1 = HashFun1()(key) % _size;
if (!_bm.HasExisted(hash1))
return false;
size_t hash2 = HashFun2()(key) % _size;
if (!_bm.HasExisted(hash2))
return false;
size_t hash3 = HashFun3()(key) % _size;
if (!_bm.HasExisted(hash3))
return false;
size_t hash4 = HashFun4()(key) % _size;
if (!_bm.HasExisted(hash4))
return false;
size_t hash5 = HashFun5()(key) % _size;
if (!_bm.HasExisted(hash5))
return false;
return true;
}
private:
BitMap _bm;
size_t _size;
};

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。