比特博文|位图布隆过滤器
Posted 西安比特教育
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了比特博文|位图布隆过滤器相关的知识,希望对你有一定的参考价值。
位图(bitmap)
位图是哈希的一种扩展,本质上是一种数组,即每个二进制位表示一种状态,0表示不存在,1表示存在。
我们用腾讯的一道大数据题引出位图结构吧。比如说:给40亿个不重复且无序的无符号整数,现在给你一个整数让你快速判断出它是否存在?(假设我们只有4G内存)
这道题就是典型的海量数据处理,40亿个数需要160亿字节,等同于16GB,一次性是无法将40亿个数据加入到内存中的,因此引入了位图。
对于这些无符号整数我们只需要两种状态来标识,0标识不存在,1标识存在,因此40亿无符号整数只需要2^32/8=512MB,显然这是可以接受的。
#include <iostream>
#include <vector>
using namespace std;
class bitMap
{
public:
//1.处理整数
bitMap(size_t N ) //N代表需要判断的数据个数
{
_array.resize((N >> 5) + 1); //N/32 + 1需要开辟的字节个数
}
//2.处理字符串
bitMap(string bit)
{
for (size_t idx = 0; idx < bit.size(); ++idx)
{
//合法值检测(bitMap中只有0,1合法)
if (bit[idx] != '0' || bit[idx] != '1')
return;
}
_array.resize((bit.size() >> 5) + 1); //size()/32 + 1需要开辟的字节个数
//对字符串中的有效位置置1
for (size_t idx = 0; idx < bit.size(); ++idx)
{
if (bit[idx] == '1')
Set(idx);
}
}
//设置位状态为1
void Set(size_t value)
{
size_t index = value >> 5;//代表字节的下标
size_t num = value % 32; //代表当前字节中位的下标
_array[index] |= (1 << num);//将特定位置置1
}
//重置位状态为0
void ReSet(size_t value)
{
size_t index = value >> 5; //代表字节的下标
size_t num = value % 32; //代表当前字节中位的下标
_array[index] &= (~(1 << num)); //将特定位置置0
}
//判断是否存在,返回位状态
bool isFind(size_t value)
{
size_t index = value >> 5;
size_t num = value % 32;
return _array[index] & (1 << num);
}
private:
vector<size_t> _array; //每个size_t可以判断32个数是否存在
};
int main()
{
bitMap bm((size_t) - 1);
bm.Set(10);
bm.Set(20);
bm.Set(30);
bm.Set(40);
bm.Set(50);
bm.Set(60);
bm.Set(70);
bm.Set(80);
cout << bm.isFind(10) << endl;
cout << bm.isFind(11) << endl;
cout << bm.isFind(80) << endl;
bm.ReSet(10);
bm.ReSet(40);
bm.ReSet(70);
cout << bm.isFind(10) << endl;
cout << bm.isFind(20) << endl;
cout << bm.isFind(30) << endl;
cout << bm.isFind(40) << endl;
cout << bm.isFind(50) << endl;
cout << bm.isFind(60) << endl;
cout << bm.isFind(70) << endl;
cout << bm.isFind(80) << endl;
system("pause");
return 0;
}
布隆过滤器(bloomfiliter)
布隆过滤器是哈希+位图的变种,它的基本思想是:通过一个Hash函数将一个元素映射成一个位矩阵中的一个点,我们只需查看这个点是不是1就知道集合中是否存在它。
注意:对于布隆过滤器来说,存在不一定存在,但不存在一定不存在。
//hashFunc.h
#pragma once
#include <iostream>
using namespace std;
struct _HashFunc1
{
size_t operator()(const string& str)
{
size_t num=0;
for (int i = 0; i < (int)str.size();i++)
{
num = num * 131 +str[i];
}
return num;
}
};
struct _HashFunc2
{
size_t operator()(const string& str)
{
size_t num=0;
for (int i =0; i < (int)str.size(); i++)
{
num = num * 65599 + str[i];
}
return num;
}
};
struct _HashFunc3
{
size_t operator()(const string& str)
{
size_t magic = 63689;
size_t num = 0;
for (int i = 0; i < (int)str.size(); i++)
{
num = num *magic + str[i];
magic *= 378551;
}
return num;
}
};
struct _HashFunc4
{
size_t operator()(const string& str)
{
size_t num = 0;
for (int i = 0; i < (int)str.size(); i++)
{
if ((i & 1) == 0)
{
num ^= ((num << 7) ^ str[i] ^ (num >> 3));
}
else
{
num^= (~((num << 11) ^ str[i]^ (num >> 5)));
}
}
return num;
}
};
struct _HashFunc5
{
size_t operator()(const string& str)
{
if (str.empty())
return 0;
size_t num = 5381;
for (int i = 0; i < (int)str.size(); i++)
{
num =num* 33 ^str[i];
}
return num;
}
};
//bloomfliter.h
#include "hashFunc.h"
#include <vector>
template<typename K=string
,class HashFunc1=_HashFunc1
, class HashFunc2 = _HashFunc2
, class HashFunc3= _HashFunc3
, class HashFunc4= _HashFunc4
, class HashFunc5 = _HashFunc5>
class BloomFilter
{
public:
BloomFilter(size_t range)
{
_bitmap.resize(range*5); //利用5个哈希函数映射一个元素
}
//将5个位置全部置1
void Set(const K& key)
{
size_t index1 = HashFunc1()(key) % _bitmap.size();
size_t index2 = HashFunc2()(key) % _bitmap.size();
size_t index3 = HashFunc3()(key) % _bitmap.size();
size_t index4 = HashFunc4()(key) % _bitmap.size();
size_t index5 = HashFunc5()(key) % _bitmap.size();
_bitmap[index1]++;
_bitmap[index2]++;
_bitmap[index3]++;
_bitmap[index4]++;
_bitmap[index5]++;
}
//采用引用计数的方式复位
bool ReSet(const K& key)
{
size_t index1 = HashFunc1()(key) % _bitmap.size();
size_t index2 = HashFunc2()(key) % _bitmap.size();
size_t index3 = HashFunc3()(key) % _bitmap.size();
size_t index4 = HashFunc4()(key) % _bitmap.size();
size_t index5 = HashFunc5()(key) % _bitmap.size();
//只要有一个位置为0,则证明该元素不存在
if (_bitmap[index1] == 0 ||
_bitmap[index2] == 0 ||
_bitmap[index3] == 0 ||
_bitmap[index4] == 0 ||
_bitmap[index5] == 0)
return false;
//要是都不为0,才减一
_bitmap[index1]--;
_bitmap[index2]--;
_bitmap[index3]--;
_bitmap[index4]--;
_bitmap[index5]--;
return true;
}
//判断元素是否存在
bool Test(const K& key)
{
size_t index1 = HashFunc1()(key) % _bitmap.size();
size_t index2 = HashFunc2()(key) % _bitmap.size();
size_t index3 = HashFunc3()(key) % _bitmap.size();
size_t index4 = HashFunc4()(key) % _bitmap.size();
size_t index5 = HashFunc5()(key) % _bitmap.size();
//只有五个位置都为1,才存在
if (_bitmap[index1] != 0 &&
_bitmap[index2] != 0 &&
_bitmap[index3] != 0 &&
_bitmap[index4] != 0 &&
_bitmap[index5] != 0)
return true;
return false;
}
private:
vector<size_t> _bitmap;
};
//bloomfliter.h
#include "hashFunc.h"
#include <vector>
template<typename K=string
,class HashFunc1=_HashFunc1
, class HashFunc2 = _HashFunc2
, class HashFunc3= _HashFunc3
, class HashFunc4= _HashFunc4
, class HashFunc5 = _HashFunc5>
class BloomFilter
{
public:
BloomFilter(size_t range)
{
_bitmap.resize(range*5); //利用5个哈希函数映射一个元素
}
//将5个位置全部置1
void Set(const K& key)
{
size_t index1 = HashFunc1()(key) % _bitmap.size();
size_t index2 = HashFunc2()(key) % _bitmap.size();
size_t index3 = HashFunc3()(key) % _bitmap.size();
size_t index4 = HashFunc4()(key) % _bitmap.size();
size_t index5 = HashFunc5()(key) % _bitmap.size();
_bitmap[index1]++;
_bitmap[index2]++;
_bitmap[index3]++;
_bitmap[index4]++;
_bitmap[index5]++;
}
//采用引用计数的方式复位
bool ReSet(const K& key)
{
size_t index1 = HashFunc1()(key) % _bitmap.size();
size_t index2 = HashFunc2()(key) % _bitmap.size();
size_t index3 = HashFunc3()(key) % _bitmap.size();
size_t index4 = HashFunc4()(key) % _bitmap.size();
size_t index5 = HashFunc5()(key) % _bitmap.size();
//只要有一个位置为0,则证明该元素不存在
if (_bitmap[index1] == 0 ||
_bitmap[index2] == 0 ||
_bitmap[index3] == 0 ||
_bitmap[index4] == 0 ||
_bitmap[index5] == 0)
return false;
//要是都不为0,才减一
_bitmap[index1]--;
_bitmap[index2]--;
_bitmap[index3]--;
_bitmap[index4]--;
_bitmap[index5]--;
return true;
}
//判断元素是否存在
bool Test(const K& key)
{
size_t index1 = HashFunc1()(key) % _bitmap.size();
size_t index2 = HashFunc2()(key) % _bitmap.size();
size_t index3 = HashFunc3()(key) % _bitmap.size();
size_t index4 = HashFunc4()(key) % _bitmap.size();
size_t index5 = HashFunc5()(key) % _bitmap.size();
//只有五个位置都为1,才存在
if (_bitmap[index1] != 0 &&
_bitmap[index2] != 0 &&
_bitmap[index3] != 0 &&
_bitmap[index4] != 0 &&
_bitmap[index5] != 0)
return true;
return false;
}
private:
vector<size_t> _bitmap;
};
END
以上是关于比特博文|位图布隆过滤器的主要内容,如果未能解决你的问题,请参考以下文章