Bloom Filter 布隆過濾器 原理

2021-08-15 05:25:01 字數 4185 閱讀 2078

**:

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

[cpp]view plain

copy

////  bloomfilter.h

//  bloomfilter

////  created by 劉建安 on 4/19/15.

//#ifndef bloomfilter_bloomfilter_h

#define bloomfilter_bloomfilter_h

#include "math.h"

#include "memory.h"

#include "bloomhash.h"

using

namespace

std;  

class

bloomfilter; 

//hash函式的種子

for(

inti = 0; i < 7; i++)  

hash[i].setseed(seeds[i]);  

}  //判斷是否包含某個字串

bool

iscontain(string s)  

return

flag;  

}  //新增字串

void

add(string s)  

}  };  

#endif

bloomhash.h

[cpp]view plain

copy

////  bloomhash.h

//  bloomfilter

////  created by 劉建安 on 4/19/15.

//#ifndef bloomfilter_bloomhash_h

#define bloomfilter_bloomhash_h

#include "string"

using

namespace

std;  

#define numofbits (1 << 14) //bits陣列的長度

class

bloomhash  

//對乙個字串求雜湊值

inthash(string s)  

return

(numofbits -1) & result; 

//這裡記得要減去1,否則答案有錯;&是為了保證陣列不越界

}  };  

#endif

main.cpp

[cpp]view plain

copy

////  main.cpp

//  bloomfilter

////  created by 劉建安 on 4/19/15.

//#include 

#include "bloomfilter.h"

#include "string"

using

namespace

std;  

intmain(

intargc, 

const

char

* argv)   

else

cout << "no"

<< endl;  

return

0;  

}  

Bloom filter(布隆過濾器)

問題 在網路爬蟲中,有乙個要考慮的問題,由於網路間的鏈結錯綜複雜,蜘蛛在網路間爬行很可能會形成 環 為了避免形成 環 就需要知道蜘蛛已經訪問過那些url。給乙個url,怎樣知道蜘蛛是否已經訪問過呢?有如下幾種方案 1.將訪問過的url儲存到資料庫。2.用hashset將訪問過的url儲存起來。那只需...

布隆過濾器(Bloom Filter)

1.簡介 布隆過濾器是一種多雜湊函式對映的快速查詢演算法。它可以判斷出某個元素肯定不在集合裡或者可能在集合裡,即它不會漏報,但可能會誤報。通常應用在一些需要快速判斷某個元素是否屬於集合,但不嚴格要求100 正確的場合。2.原理 首先需要k個hash函式,每個函式可以把key雜湊成為1個整數 初始化時...

布隆過濾器(BloomFilter)

名稱 問題解決方法 快取穿透 查詢了乙個不存在的資料 布隆過濾器 快取擊穿 某個key的快取失效 互斥鎖快取雪崩 多個key的快取同時失效 失效時間 隨機時間 底層是乙個bit二進位制向量或叫 bit 陣列,bit 裡存放的資料非0即1。通過雜湊函式將元素對映到bit的相應位置,並將此位置置為1。如...