bloom filter概念讲解以及代码分析

一. 简介
1.什么是bloom filter?
Bloom filter 是由 Howard Bloom 在 1970 年提出的二进制向量数据结构,它具有很好的空间和时间效率,被用来检测一个元素是不是集合中的一个成员,这种检测只会对在集合内的数据错判,而不会对不是集合内的数据进行错判,这样每个检测请求返回有“在集合内(可能错误)”和“不在集合内(绝对不在集合内)”两种情况,可见 Bloom filter 是牺牲了正确率换取时间和空间。

2.bloom filter的计算方法?
如需要判断一个元素是不是在一个集合中,我们通常做法是把所有元素保存下来,然后通过比较知道它是不是在集合内,链表、树都是基于这种思路,当集合内元素个数的变大,我们需要的空间和时间都线性变大,检索速度也越来越慢。 Bloom filter 采用的是哈希函数的方法,将一个元素映射到一个 m 长度的阵列上的一个点,当这个点是 1 时,那么这个元素在集合内,反之则不在集合内。这个方法的缺点就是当检测的元素很多的时候可能有冲突,解决方法就是使用 k 个哈希 函数对应 k 个点,如果所有点都是 1 的话,那么元素在集合内,如果有 0 的话,元素则不在集合内。

3.bloom filter的特点?
Bloom filter 优点就是它的插入和查询时间都是常数,另外它查询元素却不保存元素本身,具有良好的安全性。它的缺点也是显而易见的,当插入的元素越多,错判“在集合内”的概率就越大了,另外 Bloom filter 也不能删除一个元素,因为多个元素哈希的结果可能在 Bloom filter 结构中占用的是同一个位,如果删除了一个比特位,可能会影响多个元素的检测。

二. 代码实现
现下面在linux下实现了bloom filter的功能代码:


代码如下:

// bloom.h:
#ifndef __BLOOM_H__
#define __BLOOM_H__

#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_create(size_t size, size_t nfuncs, ...);
int bloom_destroy(BLOOM *bloom);
int bloom_add(BLOOM *bloom, const char *s);
int bloom_check(BLOOM *bloom, const char *s);

#endif

// bloom.c:
#include<limits.h>
#include<stdarg.h>

#include"bloom.h"

#define SETBIT(a, n) (a[n/CHAR_BIT] |= (1<<(n%CHAR_BIT)))
#define GETBIT(a, n) (a[n/CHAR_BIT] & (1<<(n%CHAR_BIT)))

BLOOM *bloom_create(size_t size, size_t nfuncs, ...)
{
BLOOM *bloom;
va_list l;
int n;

if(!(bloom=malloc(sizeof(BLOOM)))) return NULL;
if(!(bloom->a=calloc((size+CHAR_BIT-1)/CHAR_BIT, 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);

bloom->nfuncs=nfuncs;
bloom->asize=size;

return bloom;
}

int bloom_destroy(BLOOM *bloom)
{
free(bloom->a);
free(bloom->funcs);
free(bloom);

return 0;
}

int bloom_add(BLOOM *bloom, const char *s)
{
size_t n;

for(n=0; n<bloom->nfuncs; ++n) {
SETBIT(bloom->a, bloom->funcs[n](s)%bloom->asize);
}

return 0;
}

int bloom_check(BLOOM *bloom, const char *s)
{
size_t n;

for(n=0; n<bloom->nfuncs; ++n) {
if(!(GETBIT(bloom->a, bloom->funcs[n](s)%bloom->asize))) return 0;
}

return 1;
}

// test.c:
#include<stdio.h>
#include<string.h>

#include"bloom.h"
//下面为两种哈希算法函数
unsigned int sax_hash(const char *key)
{
unsigned int h=0;

while(*key) h^=(h<<5)+(h>>2)+(unsigned char)*key++;

return h;
}

unsigned int sdbm_hash(const char *key)
{
unsigned int h=0;
while(*key) h=(unsigned char)*key++ + (h<<6) + (h<<16) - h;
return h;
}

int main(int argc, char *argv[])
{
FILE *fp;
char line[1024];
char *p;
BLOOM *bloom;

if(argc<2) {
fprintf(stderr, "ERROR: No word file specified\n");
return EXIT_FAILURE;
}

if(!(bloom=bloom_create(2500000, 2, sax_hash, sdbm_hash))) {
fprintf(stderr, "ERROR: Could not create bloom filter\n");
return EXIT_FAILURE;
}

if(!(fp=fopen(argv[1], "r"))) {
fprintf(stderr, "ERROR: Could not open file %s\n", argv[1]);
return EXIT_FAILURE;
}

while(fgets(line, 1024, fp)) {
if((p=strchr(line, '\r'))) *p='\0';//回车
if((p=strchr(line, '\n'))) *p='\0';//换行

bloom_add(bloom, line);
}

fclose(fp);

while(fgets(line, 1024, stdin)) {
if((p=strchr(line, '\r'))) *p='\0';
if((p=strchr(line, '\n'))) *p='\0';

p=strtok(line, " \t,.;:\r\n?!-/()");
while(p) {
if(!bloom_check(bloom, p)) {
printf("No match for ford \"%s\"\n", p);
}
                    else
                      printf("match for ford \"%s\"\n",p);
p=strtok(NULL, " \t,.;:\r\n?!-/()");
}
}

bloom_destroy(bloom);

return EXIT_SUCCESS;
}

// Makefile:
   all: bloom

bloom: bloom.o test.o
           cc -o bloom -Wall -pedantic bloom.o test.o

bloom.o: bloom.c bloom.h
           cc -o bloom.o -Wall -pedantic -ansi -c bloom.c

test.o: test.c bloom.h
           cc -o test.o -Wall -pedantic -ansi -c test.c

(0)

相关推荐

  • bloom filter概念讲解以及代码分析

    一. 简介1.什么是bloom filter?Bloom filter 是由 Howard Bloom 在 1970 年提出的二进制向量数据结构,它具有很好的空间和时间效率,被用来检测一个元素是不是集合中的一个成员,这种检测只会对在集合内的数据错判,而不会对不是集合内的数据进行错判,这样每个检测请求返回有"在集合内(可能错误)"和"不在集合内(绝对不在集合内)"两种情况,可见 Bloom filter 是牺牲了正确率换取时间和空间. 2.bloom filter的计

  • C#中闭包概念讲解

    理解C#中的闭包 1. 闭包的含义 首先闭包并不是针对某一特定语言的概念,而是一个通用的概念.除了在各个支持函数式编程的语言中,我们会接触到它.一些不支持函数式编程的语言中也能支持闭包(如java8之前的匿名内部类). 在看过的对于闭包的定义中,个人觉得比较清晰的是在<JavaScript高级程序设计>这本书中看到的.具体定义如下: 闭包是指有权访问另一个函数作用域中的变量的函数. 注意,闭包这个词本身指的是一种函数.而创建这种特殊函数的一种常见方式是在一个函数中创建另一个函数. 2. 在C#

  • Python Counting Bloom Filter原理与实现详细介绍

    目录 前言 原理 一.BF 为什么不支持删除 二.什么是 Counting Bloom Filter 三.Counter 大小的选择 简单的实现 总结 前言 标准的 Bloom Filter 是一种比较简单的数据结构,只支持插入和查找两种操作.在所要表达的集合是静态集合的时候,标准 Bloom Filter 可以很好地工作,但是如果要表达的集合经常变动,标准Bloom Filter的弊端就显现出来了,因为它不支持删除操作.这就引出来了本文要谈的 Counting Bloom Filter,后文简

  • Java的RTTI和反射机制代码分析

    RTTI,即Run-Time Type Identification,运行时类型识别.运行时类型识别是Java中非常有用的机制,在Java运行时,RTTI维护类的相关信息.RTTI能在运行时就能够自动识别每个编译时已知的类型. 很多时候需要进行向上转型,比如Base类派生出Derived类,但是现有的方法只需要将Base对象作为参数,实际传入的则是其派生类的引用.那么RTTI就在此时起到了作用,比如通过RTTI能识别出Derive类是Base的派生类,这样就能够向上转型为Derived.类似的,

  • javaweb设计中filter粗粒度权限控制代码示例

    1 说明 我们给出三个页面:index.jsp.user.jsp.admin.jsp. index.jsp:谁都可以访问,没有限制: user.jsp:只有登录用户才能访问: admin.jsp:只有管理员才能访问. 2 分析 设计User类:username.password.grade,其中grade表示用户等级,1表示普通用户,2表示管理员用户. 当用户登录成功后,把user保存到session中. 创建LoginFilter,它有两种过滤方式: 如果访问的是user.jsp,查看sess

  • Java语言求解完美数代码分析

    1.概念 首先我们理解一下,什么叫做完美数? 问题描述:若一个自然数,它所有的真因子(即除了自身以外的约数)的和恰好等于它本身,这种数叫做完全数.简称"完数" 例如, 6=1+2+3 28=1+2+4+7+14 496=1+2+4+8+16+31+62+124+248 8128=1+2+4+8+16+32+64+127+254+508+1016+2032+4064 按照完数的定义,其实用程序求解完数并不是太难,先求解出这个数的所有真因子,然后相加,判断是否等于它本身即可.但是,在这个数

  • Python yield与实现方法代码分析

    yield的功能类似于return,但是不同之处在于它返回的是生成器. 生成器 生成器是通过一个或多个yield表达式构成的函数,每一个生成器都是一个迭代器(但是迭代器不一定是生成器). 如果一个函数包含yield关键字,这个函数就会变为一个生成器. 生成器并不会一次返回所有结果,而是每次遇到yield关键字后返回相应结果,并保留函数当前的运行状态,等待下一次的调用. 由于生成器也是一个迭代器,那么它就应该支持next方法来获取下一个值. 基本操作 # 通过`yield`来创建生成器 def f

  • java语言求解兔子问题代码分析

    1.思考 兔子问题,是费氏数列的形象化说法,它是由一位名为Fibonacci的数学家在它的著作中提出的一个问题. 2.描述 它体术的问题是:若有一只免子每个月生一只小免子,一个月后小免子也开始生产.起初只有一只免子,一个月后就有两只免子,二个月后有三只免子,三个月后有五只免子(小免子投入生产)...... 我们使用数学的方式表达出来,便是下面的一组数列: 1.1.2.3.5.8.13.21.34.55.89...... 注意:新生的小免子需一个月成长期才会投入生产!而且这些兔子是不死的哦!!!

  • php桥接模式的实例用法及代码分析

    说明 1.将两个原本不相关的类结合在一起,然后利用两个类中的方法和属性,输出一份新的结果. 2.结构分为Abstraction抽象类.RefindAbstraction被提炼的抽象类.Implementor实现类.ConcreteImplementor具体实现类 .Client客户端代码. 实例 /** * 颜色抽象类 * Class Colour */ abstract class Colour { /** * @return mixed */ abstract public function

  • Redis中Bloom filter布隆过滤器的学习

    目录 1.概念 2.guava实现 2.1.依赖 2.2.初始化布隆过滤器 2.3.布隆过滤器 2.4.添加元素或者判断是否存在 3.Redisson实现 3.1.依赖 3.2.注入或测试 1.概念 ​ 布隆过滤器是一个高空间利用率的概率性数据结构,主要目的是节省内存空间以及判断一个元素是否存在于一个集合中(存在误判的情况),可以理解为一个不怎么精确的 set 结构,当你使用它的 contains 方法判断某个对象是否存在时,它可能会误判.但是布隆过滤器也不是特别不精确,只要参数设置的合理,它的

随机推荐