布隆过滤器

布隆过滤器的实现(c++)

简要介绍一下布隆过滤器:

如果想要判断一个元素是不是在一个集合里,一般想到的是将所有元素保存起来,然后通过比较确定。链表,树等等数据结构都是这种思路. 但是随着集合中元素的增加,我们需要的存储空间越来越大,检索速度也越来越慢(O(n),O(logn))。不过世界上还有一种叫作散列表(又叫哈希表,Hash table)的数据结构。它可以通过一个Hash函数将一个元素映射成一个位阵列(Bit array)中的一个点。这样一来,我们只要看看这个点是不是1就可以知道集合中有没有它了。这就是布隆过滤器的基本思想。(摘自百度百科)

实现:

1.计算需要的哈希函数个数k及需要申请的内存长度m(m是二进制长度 ,申请时可以申请((m/32)+1 个int 类型),

2.将文件中的每一个样本经k个哈希函数求得k个哈希值 ,并对每一个哈希值取模(哈希值%m),并将申请的内存中对应位置1(如果本来是1,则不改变),

3.判断某样本是否存在,只需重复第二步,根据哈希函数计算每一个哈希值,取模并看内存中的每个对应位是否为1。

查找的时间复杂度为O(1)。

且并不能保证零失误率(本来在集合里的元素一定可以判断正确,但是不在集合中的元素也有可能判断为在集合中)。

下图为m,k的计算公式,其中n为样本数量,p为样本失误率,k为需要哈希函数的个数,m为需要申请的内存长度(注意是二进制)。

P真为 真实的失误率。

代码如下:

//接口
#ifndef _BLOOMFILTER_
#define _BLOOMFILTER_
 
#include<math.h>
#include<vector>
using namespace std;
unsigned int SDBMHash(const char *str);
unsigned int RSHash(const char *str);
unsigned int JSHash(const char *str);
unsigned int PJWHash(const char *str);
unsigned int APHash(const char *str);
unsigned int DJBHash(const char *str);
unsigned int ELFHash(const char *str);
unsigned int BKDRHash(const char *str);
class Bloomfilter{
public:
	Bloomfilter(double err_rate,int num,char* path);	//传入样本的文档路径,样本个数,期望的失误率,注意计算得到的哈希函数个数k需要不大于hashtable的size
    ~Bloomfilter();
    bool is_contain(const char* str);	//查看字符串是否在样本中存在
    int hashnum();				//返回k
       // double real_precision();	//返回真实的失误率
    int sizeofpool();				//返回len
	void filter_init();		//初始化布隆过滤器
private:
	void listinit();				//打开path路径的文档,计算每一行样本到内存bitpool中
	int  hashtable_init();			//把几个哈希函数加入到vector<unsigned (*)(const char*)> hastable容器中,必须大于k
	int len; 
	char* mypath;			//文件的路径,通过构造函数传入路径
    Bloomfilter()=delete;
    double precision;
    int *bitpool;		//需要内存的长度,在构造函数中申请
	int bitpoollen;		//需要的二进制位数m
	int hashfuncnum;	//需要的哈希函数的个数k, k <=hashtable.size();
	int samplenum;		//样本个数,构造函数传入
	vector<unsigned int (*)(const char*)> hashtable;	//存放计算字符串哈希值的哈希函数
};
#endif
//实现
#include<iostream>
#include<string>
#include<math.h>
#include<stdio.h>
#include"bloomfilter.h"
#include<fstream>
double lg2(double n)
{
	return log(n)/log(2);
}
 
 
using namespace std;
 
int Bloomfilter::hashtable_init()
{
	hashtable.push_back(*PJWHash);
	hashtable.push_back(*JSHash);
	hashtable.push_back(*RSHash);
	hashtable.push_back(*SDBMHash);
	hashtable.push_back(*APHash);
	hashtable.push_back(*DJBHash);
	hashtable.push_back(*BKDRHash);
	hashtable.push_back(*ELFHash);
	return hashtable.size();
 
}
 
 
 
Bloomfilter::Bloomfilter(double err_rate,int num,char* path)
{
	mypath=path;
	samplenum=num;
	bitpoollen=-((samplenum*log(err_rate))/(log(2)*log(2)));
	hashfuncnum=0.7*(bitpoollen/samplenum);
	len=bitpoollen/32+1;
	bitpool=new int[len];
}
int Bloomfilter::hashnum()
{
 
	return hashfuncnum;
}
int Bloomfilter::sizeofpool()
{
 
	return len;
}
 
void Bloomfilter::filter_init()
{
	hashtable_init();
	if(hashfuncnum>hashtable.size())
	{
		cout<<"哈系表中的函数不足,请添加"<<endl;
		exit(0);
	}
	listinit();				
}
 
bool Bloomfilter::is_contain(const char* str)
{
	int  hashval;
	for(int i=0;i!=hashfuncnum;i++)
	{
		hashval=hashtable[i](str);
		//cout<<hashval<<" ";   //test
		hashval=hashval%(len*32); //len*32为bitpool的总位数
		if(bitpool[hashval/32]&(0x1<<(hashval%32)))
			continue;
		else
			return false;
 
	}
	return true;
} 
void Bloomfilter::listinit()
{
        FILE* fp;
        char* buf;
        size_t length=0;
	fp=fopen(mypath,"r+");
	int hashval;
	char* p;
	while(getline(&buf,&length,fp)!=EOF)
	{
		
		p=buf;
		while(*p!='\n')
		{
			p++;
		}
		*p='\0';
 
		for(int i=0;i!=hashfuncnum;i++)
		{
			
			hashval=hashtable[i](buf);		
		//	cout<<hashval<<" ";	//test
			hashval=hashval%(len*32);
			bitpool[hashval/32]|=(0x1<<(hashval%32));
		}
	}
	fclose(fp);
}
 
Bloomfilter::~Bloomfilter()
{
	delete  []bitpool;
}
//测试代码
#include<iostream>
#include"bloomfilter.h"
 
using namespace std;
 
 
 
int main()
{
	Bloomfilter mybloom(0.01,100,"redlist.txt");
	mybloom.filter_init();
	 cout<<"需要的哈希函数的个数 :"<<mybloom.hashnum()<<endl;
	cout<<"需要申请多少个int  :"<<mybloom.sizeofpool()<<endl;
	cout<<"www.dubai.com在我的集合中吗  :"<<(mybloom.is_contain("www.dubai.com")?"在":"不在")<<endl;
 
	cout<<"www.qq.com在我的集合中吗 :"<<(mybloom.is_contain("www.qq.com")?"在":"不在")<<endl;
 
	
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值