布隆過濾器
一、歷史背景知識
布隆過濾器(bloom filter)是2023年由布隆提出的。它實際上是乙個很長的二進位制向量和一系列隨機對映函式。布隆過濾器可以用於檢索乙個元素是否在乙個集合中。它的優點是空間效率和查詢時間都遠超過一般的演算法,缺點是有一定的誤識別率和刪除錯誤。而這個缺點是不可避免的。但是絕對不會出現識別錯誤的情況出現(即假反例false negatives,如果某個元素確實沒有在該集合中,那麼bloom filter 是不會報告該元素存在集合中的,所以不會漏報)
在 fbi,乙個嫌疑人的名字是否已經在嫌疑名單上;在網路爬蟲裡,乙個**是否被訪問過等等。最直接的方法就是將集合中全部的元素存在計算機中,遇到乙個新 元素時,將它和集合中的元素直接比較即可。一般來講,計算機中的集合是用雜湊表(hash table)來儲存的。它的好處是快速準確,缺點是費儲存空間。當集合比較小時,這個問題不顯著,但是當集合巨大時,雜湊表儲存效率低的問題就顯現出來 了。
比如說,乙個象 yahoo,hotmail 和 gmai 那樣的公眾電子郵件(email)提供商,總是需要過濾來自傳送垃圾郵件的人(spamer)的垃圾郵件。乙個辦法就是記錄下那些發垃圾郵件的 email 位址。由於那些傳送者不停地在註冊新的位址,全世界少說也有幾十億個發垃圾郵件的位址,將他們都存起來則需要大量的網路伺服器。如果用雜湊表,每儲存一億 個 email 位址, 就需要 1.6gb 的記憶體(用雜湊表實現的具體辦法是將每乙個 email 位址對應成乙個八字節的資訊指紋,然後將這些資訊指紋存入雜湊表,由於雜湊表的儲存效率一般只有 50%,因此乙個 email 位址需要占用十六個位元組。一億個位址大約要 1.6gb, 即十六億位元組的記憶體)。因此存貯幾十億個郵件位址可能需要上百 gb 的記憶體。除非是超級計算機,一般伺服器是無法儲存的[2]。
二、布隆過濾器原理以及優缺點
如果想判斷乙個元素是不是在乙個集合裡,一般想到的是將集合中所有元素儲存起來,然後通過比較確定。鍊錶、樹、雜湊表(雜湊表,hash table)等資料結構都是這種思想。但是隨著集合中元素的增加,我們需要的儲存空間越來越大。同時檢索速度也會越來越慢。
bloom filter 是一種空間效率很高的隨機資料結構,bloom filter 可以看做是對bit-map的擴充套件,它的原理是:
當乙個元素被加入集合中時,通過k個hash函式將這個元素對映成乙個位陣列(bit array)中的k個點,將它們置成1. 檢索時,我們只需要看這些點是不是都是1就能(大約)知道集合中有沒有它:
如果這些點中有任何乙個0,則被檢索元素一定不在;
如果都是1,則被檢索元素很可能在。
優點:它的優點是空間效率和查詢時間都遠遠超過一般的演算法,布隆過濾器儲存空間和插入\查詢時間都是o(k),另外,雜湊函式相互之間沒有關係,方便硬體並行實現,布隆過濾器不程式設計客棧需要儲存元素本身,在某些對保密要求非常嚴格的場合有優勢。
缺點:1、布隆過濾器的缺點和優點同樣明顯。誤算率是其中之一。隨著存入元素的增加,誤算率隨之增加。但是元素數量太少,則使用雜湊就可以了。
2、一般情況下不能從布隆過濾器中刪除元素,我們很容易想到把位陣列變成整數陣列,每插入乙個元素相應的計數器加1,這樣刪除元素時將計數器減掉就可以了。然而要保證安全地刪除元素並非這麼簡單。首先我們必須保證刪除的元素的確存在布隆過濾器裡面,另外計數器迴繞也會造成問題。
三、example
google chrome瀏覽器使用bloom filter識別惡意鏈結(能用較小的儲存空間表示較大的資料集合,簡單想就是把 每乙個url都可以對映成bit)的多,並且誤判率在萬分之一以下。
c++實現
bit_set.h
#pragma once
#include
using namespace std;
#include
class bitset
bool set(size_t num)
else
} bool reset(size_t num)
else
} bool text(size_t num)
private:
vector _a;
size_t _size;
}; hash.h
#pragma once
templateqaryqft; //各類雜湊字串轉換函式
size_t bkdrhash(const char *str)
return hash; }
template
size_t sdbmhash(const char *str)
return hash; }
template
size_t rshash(const char * str)
return hash; }
template
size_t aphash(const char *str)
else
} return hash; }
template
size_t jshash(const char* str)
size_t hash = 1315423911;
while (size_t ch = (size_t)*str++)
return hash;
} bloom_filter.h
#pragma once
#include"bite_set.h"
#include"hash.h"
#include
template
struct __hashfunk1
}; template
struct __hashfunk2
};
template
struct __hashfunk3
}; template
struct __hashfunk4
}; template
struct __hashfunk5
};
template,
class hashfunk2 = __hashfunk2,
class hashfunk3 = __hashfunk3,
class hashfunk4 程式設計客棧= __hashfunk4,
class hashfunk5 = __hashfunk5>
class boolfilter
void set(const k& key)
bool text(const k& key)
private:
bitset _a;
size_t _range;
}; 本文標題: c++ 資料結構之布隆過濾器
本文位址: /ruanjian/c/192952.html
資料結構 布隆過濾器
基於位圖的缺點 只能儲存整型,在現實中的應用有了很大的侷限性,所以又引出了一種新的雜湊變形,其實也算是點陣圖的變形 布隆過濾器。如圖,把字串經過布隆過濾器的處理,對映到位圖的多個位置,讓這幾個位置都置成1用來表示這個字串的存在。所以只要有乙個位置為0,那麼這個資料就不存在。1.本來不存在的資料,可能...
資料結構 布隆過濾器
原理 如果要判斷乙個數是不是在乙個集合裡,一半想到的是將所有的元素儲存起來,然後通過比較確定。但是隨著集合中元素的增加,需要的儲存空間越來越大,檢索速度自然會變慢。這時會有人想到使用雜湊表,將元素通過雜湊函式對映到乙個位陣列中,將相應的位元位置為1,這樣就可以判斷這個元素是不是在集合之中了。但是雜湊...
C 布隆過濾器
我們在玩手機的時候,軟體會給我們推送一些新訊息,軟體如何保證我們哪些訊息看過,哪些訊息沒看過呢?解決辦法 用乙個伺服器記錄我們看過的內容,為了保證能夠快速查詢,我們可以使用雜湊表儲存使用者資訊,但是浪費空間,我們使用位圖進行儲存,但是不能解決雜湊衝突,將雜湊表與位圖結合 布隆過濾器。是一種概率性資料...