Bloom Filter(布隆过滤器)原理

Bloom Filter(布隆过滤器)主要用于判断某个元素是否属于集合内,但是这种判断不是一定正确的。

经典问题:

假设你有数量非常庞大的URL集合,现在给你一个新的URL,要你快速判断这个URL是否在上述的URL集合中。

解决这个问题比较原始的方法是:先用一个数组把所有URL存起来,然后再扫描这个数组,判断里面是否有元素与新的这个URL相同。这样做会耗费非常大的空间和时间,是非常不妥的一种做法。

另一种非常快速的方法就是使用布隆过滤器了。如果布隆过滤器说一个元素在某个集合内,那么这个元素是很有可能在这个集合内的,但不是百分之百在;相反,如果布隆过滤器说一个元素不在这个集合内,那么这个元素一定不在这个集合内。

原理:

布隆过滤器主要使用的是hash函数,并且是同时使用多个hash函数,以便减少hash冲突。

首先,假设有7个hash函数,分别是h1(), h2() ….h7(),这里hash函数的具体内容是不定的,看你具体的程序和应用来决定。然后有一个位数组bits,元素个数为m吧,初始化为0.

下面先说往集合里添加元素的过程:

给你一个元素e,你要把它通过布隆过滤器添加到某个集合里。

首先,分别用上面的7个hash函数对e取hash值,假设结果如下:

r1 = h1(e) = 5,

r2 = h2(e) = 6,

r3 = h3(e) = 1,

r4 = h4(e) = 7,

r5 = h5(e) = 6,

r6 = h6(e) = 10,

r7 = h7(e) = 9.

这里需要注意的是,这几个hash函数中有可能返回值是相同的(比如上面的r2和r5)。

根据上面的结果,把bits对应位置为1(重复只需置一次就可以了):

bits[5] = 1

bits[6] = 1,

bits[1] = 1,

bits[7] = 1,

bits[10] = 1,

bits[9] = 1.

这就把e通过布隆过滤器加入到了集合中来。

现在假设又来一个元素e2,要添加到集合中来。假设用7个hash函数做hash得:

r1 = h1(e2) = 3,

r2 = h2(e2) = 1,

r3 = h3(e2) = 6,

r4 = h4(e2) = 14,

r5 = h5(e2) = 11,

r6 = h6(e2) = 13,

r7 = h7(e2) = 3.

再把对应bits的位置为1,

bits[3] = 1,

bits[1] = 1,

bits[6] = 1,

bits[14] = 1,

bits[11] = 1,

bits[13] = 1,

bits[3] = 1.

注意bits的长度m的大小,不要越过数组边界了。

经过上述两个元素的添加,bits变成下面这样:

bits[1] = 1,

bits[3] = 1,

bits[5] = 1,

bits[6] = 1,

bits[7] = 1,

bits[9] = 1,

bits[10] = 1,

bits[11] = 1,

bits[13] = 1,

bits[14] = 1,

其他都为0。

现在集合里面有e1和e2两个元素了。

现在要判断元素e3是否在这个集合内。

首先分别用上面的7个hash函数对e3求hash,结果假设如下:

r1 = h1(e3) = 3,

r2 = h2(e3) = 1,

r3 = h3(e3) = 6,

r4 = h4(e3) = 14,

r5 = h5(e3) = 11,

r6 = h6(e3) = 13,

r7 = h7(e3) = 3.

(很明显,这里的结果与e2的hash结果一样)

如果e3在集合内,那么上面结果对应的bits位要全都为1才行,如果有一个为0,那么e3就不在集合内。很明显,bits对应的位都为1,所以我们可以说e3很有可能在集合内,但不是百分之百。

如果是这种情况,e3的所有hash值对应的bits都为1,但是e3不在集合内。假设此时hash值计算结果为:

r1 =  h1(e3) = 3,

r2 =  h2(e3) =  6,

r3 =  h3(e3) = 7,

r4 =  h4(e3) = 9,

r5 =  h5(e3) = 11,

r6 =  h6(e3) =13,

r7 =  h7(e3) = 14,

此时虽然对应bits位都为1,但是由于e3的hash结果是由e1和e2混合而来的,所以此时e3是不存在集合中的。

相反,如果计算出所有的hash值,bits对应位中有为0 的,那么可以肯定地说这个元素一定不在集合内;因为如果在集合内的话,那么在用布隆过滤器添加元素时,就应该把这个元素所有hash值的bits对应位都置为了1.

BloomFilter的C++代码:

BloomFilter.h

//
//  BloomFilter.h
//  BloomFilter
//
//  Created by 刘建安 on 4/19/15.
//  Copyright (c) 2015 刘建安. All rights reserved.
//

#ifndef BloomFilter_BloomFilter_h
#define BloomFilter_BloomFilter_h
#include "math.h"
#include "memory.h"
#include "BloomHash.h"
using namespace std;

class BloomFilter{
private:
    bool bits[numOfBits];
    BloomHash hash[7]; //7个哈希函数

public:
    BloomFilter(){
        memset(bits, false, sizeof(bits));
        int seeds[7] = {5, 7, 11, 13, 23, 29, 37}; //hash函数的种子
        for (int i = 0; i < 7; i++)
            hash[i].setSeed(seeds[i]);
    }

    //判断是否包含某个字符串
    bool isContain(string s){
        bool flag = true;
        for (int i = 0; i < 7; i++){
            int tmp = hash[i].hash(s);
            flag = flag & bits[tmp];
        }
        return flag;
    }

    //添加字符串
    void add(string s){
        for (int i = 0; i < 7; i++){
            int hasValue = hash[i].hash(s);
            bits[hasValue] = true;
        }
    }
};

#endif

BloomHash.h

//
//  BloomHash.h
//  BloomFilter
//
//  Created by 刘建安 on 4/19/15.
//  Copyright (c) 2015 刘建安. All rights reserved.
//

#ifndef BloomFilter_BloomHash_h
#define BloomFilter_BloomHash_h
#include "string"
using namespace std;

#define numOfBits (1 << 14) //bits数组的长度

class BloomHash{
private:
    int seed;
public:
    void setSeed(int _seed){
        seed = _seed;
    }
    //对一个字符串求哈希值
    int hash(string s){
        long long result = 0;
        long long length = s.size();
        for (int i = 0; i < length; i++){
            result = seed * result + int(s[i]);
        }

        return (numOfBits -1) & result; //这里记得要减去1,否则答案有错;&是为了保证数组不越界
    }
};

#endif

main.cpp

//
//  main.cpp
//  BloomFilter
//
//  Created by 刘建安 on 4/19/15.
//  Copyright (c) 2015 刘建安. All rights reserved.
//

#include <iostream>
#include "BloomFilter.h"
#include "string"
using namespace std;

int main(int argc, const char * argv[]) {
    // insert code here...
    std::cout << "Hello, World!\n";
    string s = "hello world";
    BloomFilter bf = BloomFilter(); //布隆过滤器

    bf.add(s); 

    if (bf.isContain("helloworld")){
        cout << "yes" << endl;
    }
    else
        cout << "no" << endl;
    return 0;
}
时间: 2024-08-08 09:53:26

Bloom Filter(布隆过滤器)原理的相关文章

Bloom Filter布隆过滤器

http://blog.csdn.net/pipisorry/article/details/64127666 Bloom Filter简介 Bloom Filter是一种空间效率很高的随机数据结构,它利用位数组很简洁地表示一个集合,并能判断一个元素是否属于这个集合.布隆过滤器(英语:Bloom Filter)是1970年由布隆提出的.它实际上是一个很长的二进制向量和一系列随机映射函数.布隆过滤器可以用于检索一个元素是否在一个集合中.它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定

Bloom filter(布隆过滤器)概念与原理

写在前面 在大数据与云计算发展的时代,我们经常会碰到这样的问题.我们是否能高效的判断一个用户是否访问过某网站的主页(每天访问量上亿)或者需要统计网站的pv.uv.最直接的想法是将所有的访问者存起来,然后每次用户访问的时候与之前集合进行比较.不管是将访问信息存在内存(或数据库)都会对服务器造成非常大的压力.那是否存在一种方式,容忍一定的错误率,高效(计算复杂度.空间复杂度)的实现访问量信息的跟踪.统计呢?接下来介绍的布隆过滤器(BloomFilter)就可以满足当前的使用场景(注释:基数计数法同样

海量信息库,查找是否存在(bloom filter布隆过滤器)

Bloom Filter(布隆过滤器) 布隆过滤器用于测试某一元素是否存在于给定的集合中,是一种空间利用率很高的随机数据结构(probabilistic data structure),存在一定的误识别率(false positive),即布隆过滤器报告某一元素存在于某集合中,但是实际上该元素并不在集合中,但是没有错误识别的情形(false negative),即如果某个元素确实没有在该集合中,那么布隆过滤器是不会报告该元素存在于集合中的,没有漏报的情形出现,召回率为百分之百. 算法描述 布隆过

【redis】redis添加bloom filter布隆过滤器插件

前言 redis在4.0版本以后可通过插件的形式添加布隆过滤器,以下为具体操作. 操作 在https://github.com/RedisBloom/RedisBloom下载最新的release源码,在编译服务器进行解压编译: tar zxvf RedisBloom-1.1.1.tar.gz cd RedisBloom-1.1.1 make 得到动态库rebloom.so 启动redis时,如下启动即可加载bloom filter插件 ./redis-server /usr/local/redi

bloom filter(布隆过滤器)

今天中邪了, 觉得看看bloom filter. 看看海量数据处理的经典算法. 这是1970年提出来.  是用于检测一个元素是不是一个集合的成员. 如果检测结果为True, 则该元素不一定在该集合中. 如果检测结果为False, 表明该元素一定在这个集合中. 这说明bloom filter 具有 100%的召回率. 每个检测请求返回的结果只有两种, 也就是"在集合内(可能错误)" 和 "绝对不在集合内". 可见bloom filter 牺牲了正确率和时间, 换取空间

Bloom Filter概念和原理【转】

Bloom Filter概念和原理 Bloom Filter是一种空间效率很高的随机数据结构,它利用位数组很简洁地表示一个集合,并能判断一个元素是否属于这个集合.Bloom Filter的这种高效是有一定代价的:在判断一个元素是否属于某个集合时,有可能会把不属于这个集合的元素误认为属于这个集合(false positive).因此,Bloom Filter不适合那些“零错误”的应用场合.而在能容忍低错误率的应用场合下,Bloom Filter通过极少的错误换取了存储空间的极大节省. 集合表示和元

Bloom filters 布隆过滤器

在ITPUB上看到有人写到同一条语句连续执行两次,得出的结果截然不同,数据本身没有发生变化,关掉dynamic_sampling功能,多次查询结果是正常的.究竟是为什么? oracle通过内部函数使用布隆过滤对并行JOIN进行过滤.但是布隆过滤的精确度是依赖hash函数的好坏以及使用的hash函数数量决定的.你试试将_bloom_filter_enabled设为FALSE关掉布隆过滤:或者将_bloom_vector_elements设为一个稍大的数字.SQL> alter session se

Bloom Filter概念和原理

Bloom Filter是一种空间效率很高的随机数据结构,它利用位数组很简洁地表示一个集合,并能判断一个元素是否属于这个集合.Bloom Filter的这种高效是有一定代价的:在判断一个元素是否属于某个集合时,有可能会把不属于这个集合的元素误认为属于这个集合(false positive).因此,Bloom Filter不适合那些“零错误”的应用场合.而在能容忍低错误率的应用场合下,Bloom Filter通过极少的错误换取了存储空间的极大节省. 集合表示和元素查询 下面我们具体来看Bloom

布隆过滤器(Bloom Filter)的原理和实现

什么情况下需要布隆过滤器? 先来看几个比较常见的例子 字处理软件中,需要检查一个英语单词是否拼写正确 在 FBI,一个嫌疑人的名字是否已经在嫌疑名单上 在网络爬虫里,一个网址是否被访问过 yahoo, gmail等邮箱垃圾邮件过滤功能 这几个例子有一个共同的特点: 如何判断一个元素是否存在一个集合中? 常规思路 数组 链表 树.平衡二叉树.Trie Map (红黑树) 哈希表 虽然上面描述的这几种数据结构配合常见的排序.二分搜索可以快速高效的处理绝大部分判断元素是否存在集合中的需求.但是当集合里