哈希表拓展——布隆过滤器

  • 布隆过滤器的基本概念

布隆过滤器是由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;
}

结果演示:

            





猜你喜欢

转载自blog.csdn.net/cecilia3333/article/details/80405900