名人博客閱讀摘要二(Hash算法、HashSet、Bitmap、boomfilter)

2. 從頭到尾徹底解析Hash表算法

基本瞭解了Hash算法的思想。

最快的Hash表算法中,對於解決衝突,使用了三個Hash值,一個用於表示位置,另外兩個用於檢驗重複,思想很好,具體實現還不細看。

3. 探索hash_set

hash_set的底層數據結構是哈希表,因此要深入瞭解hash_set,必須先分析哈希表。哈希表是根據關鍵碼值(Key-Value)而直接進行訪問的數據結構,它用哈希函數處理數據得到關鍵碼值,關鍵碼值對應表中一個特定位置再由應該位置來訪問記錄,這樣可以在時間複雜性度爲O(1)內訪問到數據。但是很有可能出現多個數據經哈希函數處理後得到同一個關鍵碼——這就產生了衝突,解決衝突的方法也有很多,各大數據結構教材及考研輔導書上都會介紹大把方法。這裏採用最方便最有效的一種——鏈地址法,當有衝突發生時將具同一關鍵碼的數據組成一個鏈表。下圖展示了鏈地址法的使用:

 


 

4. Bit-map詳解

所謂的Bit-map就是用一個bit位來標記某個元素對應的Value,而Key即是該元素。由於採用了Bit爲單位來存儲數據,因此在存儲空間方面,可以大大節省。

如果說了這麼多還沒明白什麼是Bit-map,那麼我們來看一個具體的例子,假設我們要對0-7內的5個元素(4,7,2,5,3)排序(這裏假設這些元素沒有重複)。那麼我們就可以採用Bit-map的方法來達到排序的目的。要表示8個數,我們就只需要8個Bit(1Bytes),首先我們開闢1Byte的空間,將這些空間的所有Bit位都置爲0。

然後遍歷這5個元素,首先第一個元素是4,那麼就把4對應的位置爲1(可以這樣操作 p+(i/8)|(0×01<<(i%8)) 當然了這裏的操作涉及到Big-ending和Little-ending的情況,這裏默認爲Big-ending),因爲是從零開始的,所以要把第五位置爲一(如下圖):

然後再處理第二個元素7,將第八位置爲1,,接着再處理第三個元素,一直到最後處理完所有的元素,將相應的位置爲1,這時候的內存的Bit位的狀態如下:

然後我們現在遍歷一遍Bit區域,將該位是一的位的編號輸出(2,3,4,5,7),這樣就達到了排序的目的。下面的代碼給出了一個BitMap的用法:排序。

5. Bloom Filter詳解

可以看作是bitmap的擴展。

Bloom Filter是一種空間效率很高的隨機數據結構,它的原理是,當一個元素被加入集合時,通過K個Hash函數將這個元素映射成一個位陣列(Bit array)中的K個點,把它們置爲1。檢索時,我們只要看看這些點是不是都是1就(大約)知道集合中有沒有它了:如果這些點有任何一個0,則被檢索元素一定不在;如果都是1,則被檢索元素很可能在。這就是布隆過濾器的基本思想。

但BloomFilter的這種高效是有一定代價的:在判斷一個元素是否屬於某個集合時,有可能會把不屬於這個集合的元素誤認爲屬於這個集合(false positive)。因此,Bloom Filter不適合那些“零錯誤”的應用場合。而在能容忍低錯誤率的應用場合下,Bloom Filter通過極少的錯誤換取了存儲空間的極大節省。

下面我們具體來看Bloom Filter是如何用位數組表示集合的。初始狀態時,Bloom Filter是一個包含m位的位數組,每一位都置爲0。

爲了表達S={x1, x2,…,xn}這樣一個n個元素的集合,Bloom Filter使用k個相互獨立的哈希函數(Hash Function),它們分別將集合中的每個元素映射到{1,…,m}的範圍中。對任意一個元素x,第i個哈希函數映射的位置hi(x)就會被置爲1(1≤i≤k)。注意,如果一個位置多次被置爲1,那麼只有第一次會起作用,後面幾次將沒有任何效果。在下圖中,k=3,且有兩個哈希函數選中同一個位置(從左邊數第五位,即第二個“1“處)。

在判斷y是否屬於這個集合時,我們對y應用k次哈希函數,如果所有hi(y)的位置都是1(1≤i≤k),那麼我們就認爲y是集合中的元素,否則就認爲y不是集合中的元素。下圖中y1就不是集合中的元素(因爲y1有一處指向了“0”位)。y2或者屬於這個集合,或者剛好是一個false positive。

Bloom filter不支持元素的刪除,因爲會牽涉到其它元素對應位,可對其擴展:Counting bloom filter(CBF)將位數組中的每一位擴展爲一個counter,從而支持了元素的刪除操作。


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章