【数据结构与算法】【算法思想】位图
位圖BitMap
算法
public class BitMap { // Java中char類型占16bit,也即是2個字節(jié)private char[] bytes;private int nbits;//nbits 總?cè)萘?/span>public BitMap(int nbits) {this.nbits = nbits;this.bytes = new char[nbits/16+1];}//長度16 k/16 定位某一段 k%16定位段中某一位public void set(int k) {if (k > nbits) return;int byteIndex = k / 16;int bitIndex = k % 16;//將數(shù)字 A 的第 k 位設(shè)置為1:A = A | (1 << (k - 1)) bytes[byteIndex] |= (1 << bitIndex);}public boolean get(int k) {if (k > nbits) return false;int byteIndex = k / 16;int bitIndex = k % 16;//將數(shù)字 A 的第 k 位設(shè)置為0:A = A & ~(1 << (k - 1))//檢測數(shù)字 A 的第 k 位:A & (1 << (k - 1)) != 0return (bytes[byteIndex] & (1 << bitIndex)) != 0;} }布隆過濾器
使用 K 個哈希函數(shù),對同一個數(shù)字進(jìn)行求哈希值,那會得到 K 個不同的哈希值,我們分別記作 X1?,X2?,X3?,…,XK?。我們把這 K 個數(shù)字作為位圖中的下標(biāo),將對應(yīng)的 BitMap[X1?],BitMap[X2?],BitMap[X3?],…,BitMap[XK?]都設(shè)置成 true,也就是說,我們用 K 個二進(jìn)制位,來表示一個數(shù)字的存在。當(dāng)我們要查詢某個數(shù)字是否存在的時候,我們用同樣的 K 個哈希函數(shù),對這個數(shù)字求哈希值,分別得到 Y1?,Y2?,Y3?,…,YK?。我們看這 K 個哈希值,對應(yīng)位圖中的數(shù)值是否都為 true,如果都是 true,則說明,這個數(shù)字存在,如果有其中任意一個不為 true,那就說明這個數(shù)字不存在。
布隆過濾器的允許誤判。如果某個數(shù)字經(jīng)過布隆過濾器判斷不存在,那說明這個數(shù)字真的不存在,不會發(fā)生誤判;如果某個數(shù)字經(jīng)過布隆過濾器判斷存在,這個時候才會有可能誤判,有可能并不存在。調(diào)整哈希函數(shù)的個數(shù)、位圖大小跟要存儲數(shù)字的個數(shù)之間的比例,那就可以將這種誤判的概率降到非常低。
應(yīng)用
如何實現(xiàn)網(wǎng)頁爬蟲中的URL去重功能?
我們用布隆過濾器來記錄已經(jīng)爬取過的網(wǎng)頁鏈接,假設(shè)需要判重的網(wǎng)頁有 10 億,那我們可以用一個 10 倍大小的位圖來存儲,也就是 100 億個二進(jìn)制位,換算成字節(jié),那就是大約 1.2GB。之前我們用散列表判重,需要至少 100GB 的空間。相比來講,布隆過濾器在存儲空間的消耗上,降低了非常多。
**利用布隆過濾器,在執(zhí)行效率方面,比散列表更加高效。**布隆過濾器用多個哈希函數(shù)對同一個網(wǎng)頁鏈接進(jìn)行處理,CPU 只需要將網(wǎng)頁鏈接從內(nèi)存中讀取一次,進(jìn)行多次哈希計算,理論上講這組操作是 CPU 密集型的。而在散列表的處理方式中,需要讀取散列值相同(散列沖突)的多個網(wǎng)頁鏈接,分別跟待判重的網(wǎng)頁鏈接,進(jìn)行字符串匹配。這個操作涉及很多內(nèi)存數(shù)據(jù)的讀取,所以是內(nèi)存密集型的。我們知道 CPU 計算可能是要比內(nèi)存訪問更快速的,所以,理論上講,布隆過濾器的判重方式,更加快速。
筆記整理來源: 王爭 數(shù)據(jù)結(jié)構(gòu)與算法之美
參考資料:https://mp.weixin.qq.com/s/xxauNrJY9HlVNvLrL5j2hg
總結(jié)
以上是生活随笔為你收集整理的【数据结构与算法】【算法思想】位图的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: redis——集群
- 下一篇: node.js与npm下载及配置流程