/** *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
/** *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; }
/** *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; }
测试结果,可以看到有两个错误