目录
一,布隆过滤器
1.布隆过滤器的概念
布隆过滤器是 由布隆( Burton Howard Bloom )在 1970 年提出的 一种紧凑型的、比较巧妙的 概率型数据结构 ,特点是 高效地插入和查询,可以用来告诉你 “ 某样东西一定不存在或者可能存在 ” ,它是用多个哈希函数,将一个数据映射到位图结构中。此种方式 不仅可以提升查询效率,也可以节省大量的内存空间 。
2.易错点
布隆过滤器的出现主要是为了提高字符串查找的效率。而布隆过滤器的原理便是将字符串转化为整型映射到位图里面。那在这个过程中便会出现有限对无限的问题。整型值是有限的,但是字符串确是无限的。所以会出现冲突的问题,即一个多个字符串映射到同一个位图的位置上。所以在这个时候布隆过滤器对于一个字符串存在的判断是不准确的。但是布隆过滤器对于不在的判断确是准确的。
3.使用场景
因为布隆过滤器的特点:
布隆过滤器对于一个字符串存在的判断是不准确的。但是布隆过滤器对于不在的判断确是准确的。
所以这注定了布隆过滤器不能用于要求非常精确的场景下。所以布隆过滤器的使用场景都是一些容许误判的场景,比如在注册时需要确定用户注册的昵称是否存在。这个时候我们在使用布隆过滤器来映射时,我们先在布隆过滤器里映射的值里面找。在经过一番查找以后,会得到两个结果:1.存在 2.不存在。存在的结果肯定是不准确的,但是不存在的结果肯定是准确的。所以,在得到存在的结果是我们得在存储客户信息的服务器上再来一番查找。在得到不存在时便不需要再次查找。这样便起到了一个过滤的效果,提高了查询的效率。这也是布隆过滤器被叫做过滤器的原因。
二 ,布隆过滤器的实现
布隆过滤器的实现原理其实就是将字符串转化为整型然后映射到位图里面。所以,在布隆过滤器里面有两个东西比较重要:1.位图 。 2.字符串转为整型的函数。
实现:
namespace BloomFilter {
//字符串hash函数
struct BKDRHash
{
size_t operator()(const string& str)
{
size_t hash = 0;
for (auto e : str)
{
hash = hash * 131 + e; // 也可以乘以31、131、1313、13131、131313..
}
return hash;
}
};
struct APHash
{
size_t operator()( const string& str)
{
size_t hash = 0;
size_t ch;
for (size_t i = 0; i < str.size(); i++)
{
if ((i & 1) == 0)
{
hash ^= ((hash << 7) ^ str[i] ^ (hash >> 3));
}
else
{
hash ^= (~((hash << 11) ^ str[i] ^ (hash >> 5)));
}
}
return hash;
}
};
struct Rshash
{
size_t operator() ( const string& str)
{
size_t hash = 0;
size_t magic = 63689;
for (auto e : str)
{
hash = hash * magic + e;
magic *= 378551;
}
return hash;
}
};
template <size_t N, class K = string, class Funk1 = BKDRHash, class Funk2 =APHash, class Funk3 = Rshash>
class BloomFilter
{
public:
void set( const K& key)//set函数
{
size_t hash1 = Funk1()(key)%N;//计算出第一个位置
size_t hash2 = Funk2()(key)%N;//计算出第二个位置
size_t hash3 = Funk3()(key)%N;//计算出第三个位置
_bes.set(hash1);
_bes.set(hash2);
_bes.set(hash3);
}
bool test(const K& key)//test函数,返回true是不准确的。
{
size_t hash1 = Funk1()(key)%N;//计算出第一个位置
size_t hash2 = Funk2()(key)%N;//计算出第二个位置
size_t hash3 = Funk3()(key)%N;//计算出第三个位置
if (_bes.test(hash1) == false)//检测是否出现过
{
return false;
}
if (_bes.test(hash2) == false)
{
return false;
}
if (_bes.test(hash3)==false )
{
return false;
}
return true;
}
private:
bitset::bitset<N>_bes;//自定义位图
};
void test()//测试用例
{
BloomFilter<100>BLF;
BLF.set("猪八戒");
BLF.set("孙悟空");
BLF.set("白龙马");
cout<<BLF.test("猪八戒")<<" ";
cout<<BLF.test("孙悟空")<<" ";
cout<<BLF.test("白龙马")<<" ";
cout << BLF.test("ABC") << " ";
}
}