- 布隆过滤器的基本概念
布隆过滤器是由bitmap和几个hash函数实现的,主要用于检查一个元素是否存在与一个集合中。
- 布隆过滤器的优缺点
优点:查找时间和快空间效率都优于其他的算法;
缺点:有误错率。可能你要查找的元素并不存在,但是以前插入的数据刚好将你的key经过几个映射函数的bit位置为1,这就造成一种假象,你要查找的数据存在。直觉上判断这种情况发生的概率还是比较低的,能想到的就是当你的数据量很大的时候,这种错误率就明显上升了。
- 布隆过滤器的基本操作
布隆过滤器的基本操作要基于位图的基本操作来实现。
首先我们先来给定两个哈希操作函数:
hash_func.h:
#pragma once
#include<stddef.h>
size_t BKDRHash(const char* str);
size_t SDBMHash(const char* str);
hash_func.c:
#pragma once
#include<stddef.h>
size_t BKDRHash(const char* str);
size_t SDBMHash(const char* str);
[kaikai@localhost bloom_filter]$ cat hash_func.c
#include"hash_func.h"
size_t BKDRHash(const char* str){
size_t hash = 0;
size_t ch = 0;
while(ch = (size_t)*str++){
hash = hash * 131 + ch;
}
return hash;
}
size_t SDBMHash(const char* str){
size_t hash = 0;
size_t ch = 0;
while(ch = (size_t)*str++){
hash = 65599 * hash + ch;
}
return hash;
}
基于这两个操作函数,我们再来实现布隆过滤器的基本操作:
bloom_filter.h:
#pragma once
#include"bitmap.h"
#define BloomHashCount 2
typedef uint64_t(*BloomHash)(const char*);//此处定义了一个布隆过滤器的哈希函数,将字符串转成下标
typedef struct BloomFilter{
Bitmap bm;
BloomHash bloom_hash[BloomHashCount];
}BloomFilter;
void BloomFilterInit(BloomFilter* bf);
void BloomFilterDestroy(BloomFilter* bf);
void BloomFilterInsert(BloomFilter* bf,const char* str);
int BloomFilterIsExit(BloomFilter* bf,const char* str);
bloom_filter.c:
#include"bloom_filter.h"
#include"hash_func.h"
#define BitmapMaxSize 10000
void BloomFilterInit(BloomFilter* bf){
if(bf == NULL)
return;
BitmapInit(&bf->bm,BitmapMaxSize);
bf->bloom_hash[0] = SDBMHash;
bf->bloom_hash[1] = BKDRHash;
return;
}
void BloomFilterDestroy(BloomFilter* bf){
if(bf == NULL)
return;
bf->bloom_hash[0] = NULL;
bf->bloom_hash[1] = NULL;
BitmapDestroy(&bf->bm);
return;
}
void BloomFilterInsert(BloomFilter* bf,const char* str){
if(bf == NULL || str == NULL)
return;
size_t i = 0;
for(;i < BloomHashCount;++i){
size_t hash = bf->bloom_hash[i](str) %BitmapMaxSize;
BitmapSet(&bf->bm,hash);
}
return;
}
int BloomFilterIsExit(BloomFilter* bf,const char* str){
if(bf == NULL || str == NULL)
return 0;
size_t i = 0;
for(;i < BloomHashCount;++i){
uint64_t hash = bf->bloom_hash[i](str) % BitmapMaxSize;
int ret = BitmapTest(&bf->bm,hash);
if(ret == 0)
return 0;
}
return 1;
}
最后编写测试函数验证功能:
#include"bloom_filter.h"
#include"hash_func.h"
#define PRINT_HEAD printf("\n============%s============\n",__FUNCTION__);
void TestInit(){
PRINT_HEAD;
BloomFilter bf;
BloomFilterInit(&bf);
printf("bloom_hash[0] expect %p,actual %p\n",SDBMHash,bf.bloom_hash[0]);
printf("bloom_hash[1] expect %p,actual %p\n",BKDRHash,bf.bloom_hash[1]);
return;
}
void TestDestroy(){
PRINT_HEAD;
BloomFilter bf;
BloomFilterInit(&bf);
BloomFilterDestroy(&bf);
printf("bloom_hash[0] expect NULL,actual %p\n",bf.bloom_hash[0]);
printf("bloom_hash[1] expect NULL,actual %p\n",bf.bloom_hash[1]);
return;
}
void TestInsertAndIsExit(){
PRINT_HEAD;
BloomFilter bf;
BloomFilterInit(&bf);
BloomFilterInsert(&bf,"haha");
BloomFilterInsert(&bf,"hehe");
int ret = BloomFilterIsExit(&bf,"haha");
printf("ret expect 1,actual %d\n",ret);
ret = BloomFilterIsExit(&bf,"hehe");
printf("ret expect 1,actual %d\n",ret);
ret = BloomFilterIsExit(&bf,"hello");
printf("ret expect 0,actual %d\n",ret);
return;
}
int main(){
TestInit();
TestDestroy();
TestInsertAndIsExit();
return 0;
}
结果演示: