Bloom filter的实质就是位数组加多次哈希
优点:节省空间,快速
缺点:有一定误差率
适用范围:大容量数据检索
过程描述:对输入数据进行多次哈希,对相应位置1;判断是否存在时,应用同样的哈希函数检测相应位是否为1.
影响准确性的因素:
输入元素个数->n
位数组大小->m
哈系函数个数->k
误差率->e
k=(ln2)*(m/n)时e最小
m>=n*lg(1/e)时满足误差率最大为e,一般取m=1.44*n*lg(1/e)用以保证有足够的冗余0
简单实现(不包括哈希函数):
.h文件:
#ifndef __BLOOM_H__
#define __BLOOM_H__
//2011.06.17 by luna
//bloom filter
#include<stdlib.h>
typedef unsigned int (*hashfunc_t)(const char *);//哈希函数指针
typedef struct{
size_t asize;//位数
unsigned char *a;//位数组
size_t nfuncs;//哈希函数书目
hashfunc_t *funcs;//哈希函数指针
}BLOOM;//bloom过滤器结构
BLOOM *bloom_create(size_t size, size_t nfuncs, ...);
int bloom_destory(BLOOM *bloom);
int bloom_add(BLOOM *bloom, const char *s);
int bloom_check(BLOOM *bloom, const char *s);
#endif
.c文件:
#include<limits.h>
#include<stdarg.h>
#include"bloom.h"
//BIT array参见位数组实现
#define BITMASK(b) (1<<((b)%CHAR_BIT))
#define BITSLOT(b) ((b)/CHAR_BIT)
#define BITSET(a,b) ((a)[BITSLOT(b)] |= BITMASK(b))
#define BITCLEAR(a,b) ((a)[BITSLOT(b)] &= ~BITMASK(b))
#define BITTEST(a,b) ((a)[BITSLOT(b)] & BITMASK(b))
#define BITNSLOTS(nb) ((nb + CHAR_BIT - 1) / CHAR_BIT)
//create bloom array
//$begin bloom_create
BLOOM *bloom_create(size_t size, size_t nfuncs, ...)
{
BLOOM *bloom;
va_list l;
int n;
if(!(bloom = malloc(sizeof(BLOOM)))) return NULL;//分配bloom过滤器
if(!(bloom->a = calloc(BITNSLOTS(size),sizeof(char))))//分配位数组
{
free(bloom);
return NULL;
}
if(!(bloom->funcs = (hashfunc_t*)malloc(nfuncs*sizeof(hashfunc_t))))//分配哈希函数指针数组
{
free(bloom->a);
free(bloom);
return NULL;
}
va_start(l,nfuncs);//获取第一个可变参数地址
for(n = 0; n < nfuncs; n++)//给哈希指针数组赋值
{
bloom->funcs[n] = va_arg(l,hashfunc_t);//获取下一个可变参数地址
}
va_end(l);//可变参数指针置0
bloom->nfuncs = nfuncs;
bloom->asize = size;
return bloom;
}
//$end bloom_create
//destory bloom array
//$begin bloom_destory
int bloom_destory(BLOOM *bloom)
{
free(bloom->a);
free(bloom->funcs);
free(bloom);
return 0;
}
//$end bloom_destory
//add bloom array
//$begin bloom_add
int bloom_add(BLOOM *bloom, const char *s)
{
size_t n;
for(n = 0; n < bloom->nfuncs; n++)//多次哈希置位
{
BITSET(bloom->a, bloom->funcs[n](s) % bloom->asize);
}
return 0;
}
//$end bloom_add
//check the bloom array
//$begin bloom_check
int bloom_check(BLOOM *bloom, const char *s)
{
size_t n;
for(n = 0; n < bloom->nfuncs; n++)//多次哈希测位
{
if(!(BITTEST(bloom->a, bloom->funcs[n](s) % bloom->asize)))
{
return 0;
}
}
return 1;
}
//$end bloom_check