比特博文|位图布隆过滤器

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


以上是关于比特博文|位图布隆过滤器的主要内容,如果未能解决你的问题,请参考以下文章

哈希表应用(位图和布隆过滤器)

手撕STLbitset(位图)布隆过滤器

手撕STLbitset(位图)布隆过滤器

手撕STLbitset(位图)布隆过滤器

网页爬虫之布隆滤波原理及java实现

网页爬虫之布隆滤波原理及java实现