博客主页: 主页
系列专栏: C++
❤️感谢大家点赞收藏⭐评论✍️
期待与大家一起进步!
`
布隆过滤器特点是高效地插入和查询,可以用来告诉你 “某样东西一定不存在或者可能存在”,它是用多个哈希函数,将一个数据映射到位图结构中。此种方式不仅可以提升查询效率,也可以节省大量的内存空间。布隆过滤器一般用来操作的对象类型为string,因为string在位图中不好被标记
布隆过滤器的思想是将一个元素用多个哈希函数映射到一个位图中,因此被映射到的位置的比特位一定为1。所以可以按照以下方式进行查找:分别计算每个哈希值对应的比特位置存储的是否为零,只要有一个为零,代表该元素一定不在哈希表中,否则可能在哈希表中。
注意:布隆过滤器如果说某个元素不存在时,该元素一定不存在,如果该元素存在时,该元素可能存在,因为有些哈希函数存在一定的误判。
比如:在布隆过滤器中查找"alibaba"时,假设3个哈希函数计算的哈希值为:1、3、7,刚好和其他元素的比特位重叠,此时布隆过滤器告诉该元素存在,但实该元素是不存在的
为了减小失误,我们可以用多种方法计算对应字符串的下标所对应位置
struct BKDRHash
{
size_t operator()(const string& str)
{
size_t hash = 0;
for (auto ch : str)
{
hash = hash * 131 + ch;
}
//cout <<"BKDRHash:" << hash << endl;
return hash;
}
};
struct APHash
{
size_t operator()(const string& str)
{
size_t hash = 0;
for (size_t i = 0; i < str.size(); i++)
{
size_t ch = str[i];
if ((i & 1) == 0)
{
hash ^= ((hash << 7) ^ ch ^ (hash >> 3));
}
else
{
hash ^= (~((hash << 11) ^ ch ^ (hash >> 5)));
}
}
//cout << "APHash:" << hash << endl;
return hash;
}
};
struct DJBHash
{
size_t operator()(const string& str)
{
size_t hash = 5381;
for (auto ch : str)
{
hash += (hash << 5) + ch;
}
//cout << "DJBHash:" << hash << endl;
return hash;
}
};
template<size_t N,class K=string, class Hash1 = BKDRHash,
class Hash2 = APHash,
class Hash3 = DJBHash>
class BloomFilter {
public:
void Set(const K& key) {
//字符串插入
size_t hash1 = Hash1()(key) % N;
_bs.set(hash1);
size_t hash2 = Hash2()(key) % N;
_bs.set(hash2);
size_t hash3 = Hash3()(key) % N;
_bs.set(hash3);
}
bool Test(const K& key)
//检测字符串是否存在
{
//你每个哈希下标都为1,不能说明这个字符串一定存在,
//但若你有一个下标检测为0,那么一定不存在
size_t hash1 = Hash1()(key) % N;
if (_bs.test(hash1) == false)
return false;
size_t hash2 = Hash2()(key) % N;
if (_bs.test(hash2) == false)
return false;
size_t hash3 = Hash3()(key) % N;
if (_bs.test(hash3) == false)
return false;
return true;
}
private:
bitset<N> _bs;
};
给两个文件,分别有100亿个query,我们只有1G内存,如何找到两个文件交集?分别给出精确算法和近似算法
这里直接就是布隆过滤器,因为其可能存在冲突,所以为近似算法,因为结果有小概率是错误的
利用哈希切分:A与B中相同的query一定会分别进入Ai与Bi相同编号的小文件
找交集,Ai读出来放进一个set,再依次读取B的query,在就是交集并且删掉,就可以找到Ai与Bi的交集。
可能存在的情况:
两个场景:Ai有5G
1.4G都是相同的query,1G冲突
2.大多数都是冲突的,这里冲突指的是两个不同的字符串算哈希下标的时候,所有哈希下标均相同。
解决方案:
1.先把Ai的query读到一个set中,再依次读取Bi的query,如果set的insert报错抛异常(因为超出的最大容量),那么大多数的都是冲突的,因为如果我是相同的话,哪怕我有4G给相同数据,最后只插入一个,因为set有去重的功能
如果能全部insert到里面说明Ai大部分都是相同的
2.如果抛异常,说明有大量冲突,哈希下标全都重了,这个时候我们需要新换一个哈希函数,继续进行切分