bloom filter的纯C实现

API定义

/**
  *bloom_filter.h
  *
  *bloom filter算法的API定义和说明。
  *这套API没有考虑错误处理,不包含特定hash函数的实现。
  */

#ifndef BLOOM_FILTER_H_INCLUDED
#define BLOOM_FILTER_H_INCLUDED

/**
  *bloom filter算法核心类型
  *
  *核心类型用于定义bloom filter实例,其中包含算法所需的必要数据结构。
  *API用户无法也不应该直接访问bloom_filter结构体。
  */
typedef struct bloom_filter *bf_core_type;

/**
  *hash回调函数类型
  *
  *hash函数实现者应该对element元素计算hash值。
  *实现者不需要在返回前特意对hash结果模m(m含义见bf_create)。
  */
typedef unsigned long (*bf_hash_handler_type)(void *element);

/**
  *创建bloom_filter实例
  *
  *为bloom_filter实例分配内存并做部分必要的初始化,这是bloom_filter实例生命周期的开始。
  *handlers数组包含k个hash函数指针,由API用户自己分配。m设置bloom_filter实例内部记录表比特位长度。
  *handlers数组在bloom_filter实例的生命周期内必须始终存在,并且最终由API用户自己负责释放。
  *紧接着必须调用bf_clear。
  */
bf_core_type bf_create(bf_hash_handler_type handlers[], unsigned long k, unsigned long m);

/**
  *释放bf实例
  *
  *这是bf实例生命周期的终结。
  *这里不会释放bf_create中传入的handlers数组。
  */
void bf_destroy(bf_core_type bf);

/**
  *清空bf实例中已有的元素
  *
  *至少应在bf_create之后调用一次。
  */
void bf_clear(bf_core_type bf);

/**
  *向bf实例添加元素element
  */
void bf_add(bf_core_type bf, void *element);

/**
  *查询元素element是否在bf实例中
  *
  *bf中存在element则返回1,否则返回0。
  *根据bloom filter算法,返回的结果有一定的错误率。
  */
int bf_has(bf_core_type bf, void *element);

#endif // BLOOM_FILTER_H_INCLUDED

API实现

/**
  *bloom_filter.c
  *
  *bloom filter算法的简单实现,没有错误处理。
  *这里的实现并不考虑单个实例在多个线程中的同步问题,但在不同线程中使用不同的bloom filter实例是安全的。
  */

#include <string.h>
#include <stdlib.h>
#include "bloom_filter.h"

struct bloom_filter {
    bf_hash_handler_type *handlers;
    unsigned char *bitmap;
    unsigned long k, m;
};

static inline void bitset(unsigned char *bitmap, unsigned long index) {
    bitmap[index>>3]|=1<<(index&7);
}

static inline unsigned char bitget(unsigned char *bitmap, unsigned long index) {
    return 1&(bitmap[index>>3]>>(index&7));
}

bf_core_type bf_create(bf_hash_handler_type handlers[], unsigned long k, unsigned long m) {
    bf_core_type bf;
    bf=malloc(sizeof(struct bloom_filter));
    bf->k=k;
    bf->m=m;
    bf->handlers=handlers;
    bf->bitmap=malloc((m+7)>>3);
    return bf;
}

void bf_destroy(bf_core_type bf) {
    free(bf->bitmap);
    free(bf);
}

void bf_clear(bf_core_type bf) {
    memset(bf->bitmap, 0, (bf->m+7)>>3);
}

void bf_add(bf_core_type bf, void *element) {
    int i;
    for(i=0; i<bf->k; i++) {
        bitset(bf->bitmap, bf->handlers[i](element)%bf->m);
    }
}

int bf_has(bf_core_type bf, void *element) {
    int i;
    for(i=0; i<bf->k; i++) {
        if(!bitget(bf->bitmap, bf->handlers[i](element)%bf->m)) {
            return 0;
        }
    }
    return 1;
}

API测试

/**
  *test.c
  *
  *测试和演示bloom filter算法API。
  */

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "bloom_filter.h"

/**
  *简单的hash函数实现:直接返回元素的整数值。
  */
unsigned long simple_hash(void *element) {
    return *(unsigned long*)element;
}

int main() {
    //20组测试数据
    unsigned long test[20];
    unsigned long test_len=sizeof(test)/sizeof(unsigned long), i;

    //bloom filter实例
    bf_core_type bf;

    //hash回调函数数组
    bf_hash_handler_type handlers[]= {simple_hash};
    unsigned long handlers_len=sizeof(handlers)/sizeof(bf_hash_handler_type);

    //生成20组随机测试数据
    srand(time(NULL));
    for(i=0; i<test_len; i++) {
        test[i]=(unsigned long)rand();
    }

    //创建和初始化bloom filter实例
    bf=bf_create(handlers, handlers_len, 100);
    bf_clear(bf);

    //添加前10组数据元素
    for(i=0; i<test_len/2; i++) {
        bf_add(bf, test+i);
    }

    //查询全部20组数据元素
    puts("组号  数据    结果");
    for(i=0; i<test_len/2; i++) {
        printf("%-6d%-8lu%s\n", i, test[i], bf_has(bf, test+i)?"yes":"no");
    }
    puts("------------------");
    for(; i<test_len; i++) {
        printf("%-6d%-8lu%s\n", i, test[i], bf_has(bf, test+i)?"yes":"no");
    }

    //释放bloom filter实例
    bf_destroy(bf);
    return 0;
}


测试结果,可以看到有两个错误

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值