zoukankan      html  css  js  c++  java
  • 元素集合Bloom Filter

    本文纯属个人见解,是对前面学习的总结,如有描述不正确的地方还请高手指正~

        一.简介

        

        1.       布隆过滤器 (Bloom Filter)是由Burton Howard Bloom1970年提出实际上是一个很长的二进制量向和一系列随机映射数函

        2.       用于断判一个元素是不是在集合中。在垃圾邮件过滤的黑白名单方法、爬虫(Crawler)的址网判重块模中等等经常被用到。哈希表也能用于断判元素是不是在集合中,但是布隆过滤器只要需哈希表的1/81/4的空间复杂度就可以成完样同的问题。

        3.       它的点优是空间率效和查询时光都远远过超一般的算法,缺陷是有必定的误识别率和删除难题。

        

        二.基本概念

        

        1.       如果想断判一个元素是不是在一个集合里,一般想到的是将有所元素保存起来,然后通过较比肯定。链表,树等等数据结构都是这类路思.,但是元素越来越多,存储空间的需求也越来越大,检索速度慢,所以可以用利散列表(哈希)的数据结构。通过一个Hash数函映射到一位个阵列的一个点。

        2.       1亿个不重复的正整数(大致围范已知),但是只有1G的内存可用,如何断判该围范内的某个数是不是现出在这1亿个数中?最用常的处置方法是用利位图,1*108/1024*1024*8=11.9,也只要需请求12M的内存。(位图要重用于处置整型值一类的问题,而且要求无重复)

        3.       如果是一亿个邮件地址,如何断判邮件地址是不是在1亿个地址中之?这时可以用应Hash表,但是哈希表不能防止产生撞碰,设假一个邮件只占8个字节,为了证保Hash表的撞碰率,使装填因子在0.5阁下,少至要需2*8*10^8/1024*1024*1024 =1.5G存储空间,因此可以用应另外一种数据结构:Bloom Filter.

        

        三.道理:

        

        1.       布隆过滤器要需的是一位个组数(这个和位图有点似类)和k个映射数函(和Hash表似类),在初始状态时,对于长度为m的位组数array,它的有所位都被置为0,如下图所示:

        

                                                                     元素和集合

        

        2.       对于有n个元素的集合S={s1,s2......sn},通过k个映射数函{f1,f2,......fk},将集合S中的个每元素sj(1<=j<=n)映射为k个值{g1,g2......gk},然后再将位组数array中相对应的array[g1],array[g2]......array[gk]置为1

        

                                                         元素和集合

        

        3.       如果要查找某个元素item是不是在S中,则通过映射数函{f1,f2.....fk}到得k个值{g1,g2.....gk},然后再断判array[g1],array[g2]......array[gk]是不是都为1,若全为1,则itemS中,否则item不在S.这个就是布隆过滤器的实现道理.

        每日一道理
    一个安静的夜晚,我独自一人,有些空虚,有些凄凉。坐在星空下,抬头仰望美丽天空,感觉真实却由虚幻,闪闪烁烁,似乎看来还有些跳动。美的一切总在瞬间,如同“海市蜃楼”般,也只是刹那间的一闪而过,当天空变得明亮,而这星星也早已一同退去……

        4.       误判的产生有这个可能:就是集合中的若干个元素通过映射以后到得的数值恰巧包含g1,g2,.....gk,那么这类况情下可能会形成误判,但是这个概率很小,一般在万分之一以下:

        5.       布隆过滤器的误判率和这k个映射数函的计划有关

        6.       布隆过滤器是不许允删除元素的,因为若删除一个元素,可能会产生漏判的况情。不过有一种布隆过滤器的变体Counter Bloom Filter,可以持支删除元素

        

        四.用应

        

        1.       布隆过滤器在很多场所能施展很好的效果,比如:网页URL的去重,垃圾邮件的别判,集合重复元素的别判,查询减速(比如基于key-value的存储系统)等

        2.       .有两个URL集合A,B,个每集合中大约有1亿个URL,个每URL64字节,有1G的内存,如何找出两个集合中重复的URL.

        很显然,直接用利Hash表会出超内存制限的围范.这里给出两种路思:

        第一种:如果不许允必定的错误率的话,只有效分治的想思去处理,将A,B两个集合中的URL分离存到若干个文件中{f1,f2...fk}{g1,g2....gk}中,然后取f1g1的内容读入内存,将f1的内容存储到hash_map当中,然后再取g1中的url,有若雷同的url,则写入到文件中,然后直到g1的内容取读毕完,再取g2...gk.然后再取f2的内容读入内存...次依类推,道知找出有所的重复url.

        第二种:如果许允必定错误率的话,则可以用布隆过滤器的想思. 2.在停止网页爬虫时,其中有一个很要重的程过是重复URL的别判,如果将有所的url存入到数据库中,当数据库中URL的量数很多时,在判重时会形成率效低下,此时罕见的一种做法就是用利布隆过滤器,还有一种方法是用利berkeley db来存储urlBerkeley db是一种基于key-value存储的非关系数据库引擎,可以大大提高url判重的率效.

        

        五.例子:

        

    #include <string.h>
    #include <bitset>
    #include <iostream>
    #define MAX 2<<24
    using namespace std;
    
    //简化n,p 成生m的程过,直接初始化为2<<24小大
    bitset<MAX> bloomSet;
    
    //哈希数函的7个子种
    int seeds[7] = {3,7,11,13,31,37,61};
    
    //Hash Value
    int getHashValue(string str,int n){
    	int result = 0;
    	int i = 0;
    	for(i = 0;i<str.size();i++){
    		result = seeds[n]*result+(int)str[i];
    		if(result > 2<<24)
    			result %= 2<<24;
    	}
    	return result;
    }
    //断判是不是在布隆过滤器中
    bool isInBloomSet(string str){
    	int i;
    	for(i = 0;i<7;i++){
    		int hash = getHashValue(str,i);
    		if(bloomSet[hash] == 0)
    			return false;
    	}
    	return true;
    }
    
    //add Elements
    void addToBloomSet(string str){
    	int i;
    	for(int i=0;i<7;i++){
    		int hash = getHashValue(str,i);
    		bloomSet.set(hash,1);
    	}
    }
    
    //init the BloomSet
    void initBloomSet(){
    	addToBloomSet("www.baidu.com");
    	addToBloomSet("www.cnblogs.com");
    	addToBloomSet("www.google.com");
    }
    
    int main(int argc, char *argv[])
    {
       int n;
       initBloomSet();
       while(scanf("%d",&n)==1){
    	   string str;
    	   while(n--){
    		   cin >> str;
    		   if(isInBloomSet(str)){
    			   cout <<"YES"<<endl;
    		   }else{
    			   cout <<"NO"<<endl;
    		   }
    	   }
       }
      
       //system("PAUSE");	
       return 0;
    }

        
     

        

    文章结束给大家分享下程序员的一些笑话语录: 一个合格的程序员是不会写出 诸如 “摧毁地球” 这样的程序的,他们会写一个函数叫 “摧毁行星”而把地球当一个参数传进去。

  • 相关阅读:
    jquery之自定义data属性
    js获取显示器、页面等高度 (转)
    A网页高度随B内容而自然变化兼容各种浏览器
    DIV+ul+LI实现表格效果以及div带滑动条
    不同人对待问题不同态度
    MySQL,SqlServer数据库关键字在程序中处理
    一款连接SqlServer的数据库工具
    VB.Net日期格式化的5种使用方法
    MySQL与SqlServer中update操作同一个表问题
    SqlServer中存储过程 returnC#代码处理以及对应的MySQL如何改写
  • 原文地址:https://www.cnblogs.com/xinyuyuanm/p/3059998.html
Copyright © 2011-2022 走看看