zoukankan      html  css  js  c++  java
  • 浅谈BloomFilter

        首先,来看这样一个问题:在一个元素很多的集合中,判断某个元素是否在这个集合中。例如:有两个URL集合,每个集合中有1亿个URL字符串,每个字符串64字节,判断两个结合中重复的URL个数。如果使用Hash的方法,将所有的URL都存入hash表中,那么至多需要的内存是:2*1*10^8*64=12.8GB。这么大的空间需求是普通计算机的内存无法满足的。那么解决这个问题有两种方法:
            (1)使用分治的思想,将两个URL集合F与G分成若干个小文件集合{f1、f2……fk}、{g1、g2……gk},先把f1放入内存中并存入hash表,随后依次将g1、g2……gk放入内存中,与f1构成的hash表进行比对,将重复的URL挑出来存入文件中。之后,再依次放f2……fk到内存,进行下一轮的比较。
            (2)如果允许一定的误差,可以使用布隆过滤器的思想。
        布隆过滤器是由布隆在1970年提出的,是一种空间效率很高的数据结构,实际上由k个hash函数和一个range范围的bitmap位图数组组成。布隆过滤器主要是解决这种使用Hash需要开辟超大空间而无法处理的问题。它的优先是时间和空间效率都很高,缺点是可能存在一定的误差且删除困难。实现方法如下:
               1. 首先需要k个hash函数,每个函数可以把key散列成为1个整数
               2. 初始化时,需要一个长度为range比特的位图数组,每个比特位初始化为0
               3. 插入某个key到集合时,用k个hash函数计算出k个散列值,并把位图数组中对应的比特位置为1
               4. 判断某个key是否在集合时,用k个hash函数计算出k个散列值,并查询数组中对应的比特位,如果所有的比特位都是1,则在集合中。
        下面是布隆过滤器的简单实现:
    #include<iostream>
    #include<bitset>
    #include<vector>
    using namespace std;
    const int maxrang  = 2<<21;
    int seedsBuilder[10] = {3, 7, 11, 13, 31, 37, 61, 71, 79, 97};     //使用10个hash函数
    
    class StandardBloomFilter
    {
    public:
        bitset<maxrang> bloomset;
        vector<int> seeds;
        int hashNum;
        
        StandardBloomFilter()
        {
            hashNum = 0;
        }
        StandardBloomFilter(int k)
        {
            hashNum = k;
            for(int i=0 ; i<hashNum; ++i)
            {
                seeds.push_back(seedsBuilder[i]);
            }
        }
        int gethashNum(string word, int n)
        {
            int res = 0;
            for(int i=0;i<word.size();++i)
            {
                res = seeds[n]*res + (int)word[i];
                if(res > maxrang )
                    res = res % maxrang;
            }
            return res;
        }
        void add(string word)
        {
            for(int i=0; i<hashNum; ++i)
            {
                int val = gethashNum(word,i);
                bloomset.set(val, 1);
            }
        }
        bool IsContains(string &word)
        {
            for(int i=0; i<hashNum; ++i)
            {
                int val = gethashNum(word, i);
                if(bloomset[val] == 0)
                {
                    cout<<"the URL "<<word<<" is not in the URL set.
    ";
                    return false;
                }
            }
            cout<<"the URL "<<word<<" is not in the URL set.
    ";
            return true;
        }
    };
    
    int main()
    {
        StandardBloomFilter bg(6);
        StandardBloomFilter bf(6);
        bf.add("https://blog.csdn.net/u010150046/article/details/77069550");
        bf.add("http://blog.51cto.com/13449864/2082652");
        bf.add("https://www.nowcoder.com/discuss");
        bf.add("https://www.cnblogs.com/alantu2018/p/8464088.html");
        bf.add("http://www.cnblogs.com/ladawn/");
        string URL_Item = "http://www.cnblogs.com/ladawn/";
        bf.IsContains(URL_Item);
        URL_Item = "http://www.baidu.com";
        bf.IsContains(URL_Item);
        return 0;
    }
         程序运行结果如下:
  • 相关阅读:
    【转】编写高质量代码改善C#程序的157个建议——建议41:实现标准的事件模型
    【转】编写高质量代码改善C#程序的157个建议——建议40:使用event关键字为委托施加保护
    【转】编写高质量代码改善C#程序的157个建议——建议39:了解委托的实质
    【转】编写高质量代码改善C#程序的157个建议——建议38:小心闭包中的陷阱
    【转】编写高质量代码改善C#程序的157个建议——建议37:使用Lambda表达式代替方法和匿名方法
    7.FactoryBean 和BeanFactory去区别
    6.2-SingletonBeanRegistry-DefaultSingletonBeanRegistry
    6.1-AliasRegistry
    ConfigurableBeanFactory
    4.AutowireCapableBeanFactory 自动装配工厂
  • 原文地址:https://www.cnblogs.com/ladawn/p/8653343.html
Copyright © 2011-2022 走看看