热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

bloomfilter概念讲解以及代码分析

Bloomfilter优点就是它的插入和查询时间都是常数,另外它查询元素却不保存元素本身,具有良好的安全性

一. 简介
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

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
#include

#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; nbloom->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; nnfuncs; ++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; nnfuncs; ++n) {
if(!(GETBIT(bloom->a, bloom->funcs[n](s)%bloom->asize))) return 0;
}

return 1;
}  

// test.c:
#include
#include

#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


推荐阅读
  • 分布式计算助力链力实现毫秒级安全响应,确保100%数据准确性
    随着分布式计算技术的发展,其在数据存储、文件传输、在线视频、社交平台及去中心化金融等多个领域的应用日益广泛。国际知名企业如Firefox、Google、Opera、Netflix、OpenBazaar等均已采用该技术,推动了技术创新和服务升级。 ... [详细]
  • 本文介绍了进程的基本概念及其在操作系统中的重要性,探讨了进程与程序的区别,以及如何通过多进程实现并发和并行。文章还详细讲解了Python中的multiprocessing模块,包括Process类的使用方法、进程间的同步与异步调用、阻塞与非阻塞操作,并通过实例演示了进程池的应用。 ... [详细]
  • 最新进展:作为最接近官方声明的信息源,本文吸引了大量关注。若需获取最新动态,请访问:lkhill.com/ccie-version-5-update ... [详细]
  • 本文介绍了基于Java的在线办公工作流系统的毕业设计方案,涵盖了MyBatis框架的应用、源代码分析、调试与部署流程、数据库设计以及相关论文撰写指导。 ... [详细]
  • 深入解析Java并发之ArrayBlockingQueue
    本文详细探讨了ArrayBlockingQueue,这是一种基于数组实现的阻塞队列。ArrayBlockingQueue在初始化时需要指定容量,因此它是一个有界的阻塞队列。文章不仅介绍了其基本概念和数据结构,还深入分析了其源码实现,包括各种入队、出队、获取元素和删除元素的方法。 ... [详细]
  • 如何为PDF文档添加水印?简单步骤实现
    为了增强PDF文档的安全性和版权保护,添加水印是一个有效的方法。本文将介绍如何通过专业软件或在线工具轻松为PDF文档添加水印,确保您的文档在共享时仍能保持其独特性和安全性。 ... [详细]
  • 本文汇集了作者在准备研究生入学考试过程中的心得体会,包括备考策略、复习重点及应对考试的心理调适技巧,旨在为即将参加考研的学生提供实用建议。 ... [详细]
  • 垂直泊车路径设计
    本文探讨了垂直泊车路径的设计原理与实现方法。垂直泊车是指汽车从特定位置出发,经过一系列横向和纵向移动,最终达到与车位垂直停放的状态。路径设计旨在确保泊车过程既高效又安全。 ... [详细]
  • 在Linux系统中使用EncFS实现文件夹加密
    为了保护个人隐私或敏感数据不被未经授权的访问,可以通过加密技术来增强安全性。本文介绍如何在Linux系统上使用EncFS工具创建和管理加密文件夹,以确保即使在系统登录状态下,特定文件夹中的数据也保持加密状态。 ... [详细]
  • 本文探讨了在不同场景下如何高效且安全地存储Token,包括使用定时器刷新、数据库存储等方法,并针对个人开发者与第三方服务平台的不同需求提供了具体建议。 ... [详细]
  • 深入理解MongoDB的SCRAM-SHA-1认证流程
    本文详细解析了MongoDB的SCRAM-SHA-1认证机制的具体步骤,旨在帮助读者深入了解这一安全认证方法的工作原理及其在实际应用中的重要性。 ... [详细]
  • 本文探讨了在使用 MyBatis 进行批量数据处理时遇到的参数绑定异常问题,并提供了详细的解决方案。 ... [详细]
  • 本文详细介绍了如何在Windows和Linux系统上配置Openfire服务器,包括安装步骤、数据库配置及端口映射等关键环节。 ... [详细]
  • 本文详细介绍了Socket在Linux内核中的实现机制,包括基本的Socket结构、协议操作集以及不同协议下的具体实现。通过这些内容,读者可以更好地理解Socket的工作原理。 ... [详细]
  • 本文介绍了两个重要的Node.js库——cache-content-type和mime-types,它们在处理HTTP响应头时非常有用。cache-content-type是基于mime-types构建的,并且实现了缓存机制以提高性能。 ... [详细]
author-avatar
钱靖均秀蓉怡慧
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有