浅谈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.\n";
                return false;
            }
        }
        cout<<"the URL "<<word<<" is not in the URL set.\n";
        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;
}
     程序运行结果如下:

 

posted @ 2018-03-26 20:12  IvanB.G.Liu  阅读(316)  评论(0编辑  收藏  举报