BitMap 的原理和實現">BitMap 的原理和實現

分類:IT技術 時間:2017-10-05

0x00 前言

本篇是 大數據算法系列 第一篇《BitMap的原理和實現》,BitMap 的思想的和原理是很多算法的基礎,因此我們以BitMap開篇。

既然是說大數據算法,我們先嘗試給大數據算法一個定義,或者說是限定一下這個系列的範圍。

大數據算法:在給定的資源約束下,以大數據為輸入,在給定時間約束內可以計算出給定問題加過的算法。

大數據算法會有傳統的算法有不一樣的地方:

  1. 資源有約束

  2. 時間有約束

  3. 大數據作為輸入

  4. 不一定是精確算法

前三點可以看作是對算法的要求,第四點可以看作是在大數據場景下算法可以做出的讓步。比如說在10億的數據中求 count distinct 操作,完全精確的算法會十分占用空間資源,而且也很難在快速計算出結果。如果這時候允許一定的誤差,就可以在極短的時間使用少量的內容算出結果,比如基數估計算法中的Hyperloglog。

本系列會包括 BitMap、Roaring BitMap、Bloom Filter、Counting Bloom Filter、Linear Counting、Loglog Counting、HyperLogLog Counting 等算法。我會把這些算法一個個過一遍,看論文、寫代碼、整理學習筆記。

對於技術人員來講,文章應該做到 圖文碼並茂 ,因此我會盡量做到每篇文章都有原理說明和示例代碼的實現,原理說明會通過配圖的方式來理解,代碼的話會有一個比較簡單的demo。

0x01 原理

基本原理

BitMap 的基本原理就是用一個 bit 來標記某個元素對應的 Value,而 Key 即是該元素。由於采用一 個bit 來存儲一個數據,因此可以大大的節省空間。

我們通過一個具體的例子來說明 BitMap 的原理,假設我們要對 0-31 內的 3 個元素 (10, 17,28) 排序,那麽我們就可以采用 BitMap 方法(假設這些元素沒有重復)。

如下圖,要表示 32 個數,我們就只需要 32 個 bit(4Bytes),首先我們開辟 4Byte 的空間,將這些空間的所有 bit 位都置為 0。

然後,我們要添加(10, 17,28) 這三個數到 BitMap 中,需要的操作就是在相應的位置上將0置為1即可。如下圖,比如現在要插入 10 這個元素,只需要將藍色的那一位變為1即可。

將這些數據插入後,假設我們想對數據進行排序或者檢索數據是否存在,就可以依次遍歷這個數據結構,碰到位為 1 的情況,就當這個數據存在。

字符串映射

BitMap 也可以用來表述字符串類型的數據,但是需要有一層Hash映射,如下圖,通過一層映射關系,可以表述字符串是否存在。

當然這種方式會有 數據碰撞 的問題,但可以通過 Bloom Filter 做一些優化。

0x02 實現

懂原理之後,還是要寫代碼來加深一下理解,這裏用 python 實現一個最基本的版本。

代碼用到了 bitarry 庫來直接操作 bit 數組;用 hashlib 來將字符串映射到數字,以便插入 BitMap。

代碼很簡單,看懂上面的原理的話,很容易就看懂了代碼。

0x03 使用

BitMap 的使用場景很廣泛,比如說  Oracle、Redis 中都有用到 BitMap。當然更多的系統會有比 BitMap 稍微復雜一些的算法,比如 Bloom Filter、Counting  Bloom Filter,這些會在後面逐一展開。

下面舉一個在算法中用到 BitMap 來解決問題的例子。

已知某個文件內包含一些電話號碼,每個號碼為8位數字,統計不同號碼的個數。

在這裏就不再做和其它算法的對比,直接說一下 BitMap 的思路。

8 位的整數,相當於是範圍在(0,99999999),也就是說 99999999 個 bit,也就是 12M 左右的內存,比起用類似 HashMap 的方式的話能節省很大的空間。 可以理解為從0 到 99999999 的數字,每個數字對應一個 Bit位,所以只需要 12M 左右的內存表示了所有的 8 位數的電話。

查詢的時候就很簡單了,直接統計有多少位是 1 就可以了。

0x04 總結

BitMap 的思想在面試的時候還是可以用來解決不少問題的,然後在很多系統中也都會用到,算是一種不錯的解決問題的思路。

但是 BitMap 也有一些局限,因此會有其它一些基於 BitMap 的算法出現來解決這些問題。

  • 數據碰撞。比如將字符串映射到 BitMap 的時候會有碰撞的問題,那就可以考慮用 Bloom Filter 來解決,Bloom Filter 使用多個 Hash 函數來減少沖突的概率。

  • 數據稀疏。又比如要存入(10,8887983,93452134)這三個數據,我們需要建立一個 99999999 長度的 BitMap ,但是實際上只存了3個數據,這時候就有很大的空間浪費,碰到這種問題的話,可以通過引入 Roaring BitMap 來解決。


Tags: 算法 數據 原理 BitMap 可以 給定

文章來源:


ads
ads

相關文章
ads

相關文章

ad