BitMap 的基本原理和實現

前言

文章是本身寫了後先發到了公衆號裏,再轉到了內部的KM。算是一個系列的學習筆記,一篇篇來。面試

本篇是大數據算法系列 第一篇《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。優化

1、原理

基本原理

BitMap 的基本原理就是用一個 bit 來標記某個元素對應的 Value,而 Key 便是該元素。因爲採用一 個bit 來存儲一個數據,所以能夠大大的節省空間。spa

咱們經過一個具體的例子來講明 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 作一些優化。

2、實現

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

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

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

3、使用

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 就能夠了。

4、總結

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

可是 BitMap 也有一些侷限,所以會有其它一些基於 BitMap 的算法出現來解決這些問題。

  • 數據碰撞。好比將字符串映射到 BitMap 的時候會有碰撞的問題,那就能夠考慮用 Bloom Filter 來解決,Bloom Filter 使用多個 Hash 函數來減小衝突的機率。
  • 數據稀疏。又好比要存入(10,8887983,93452134)這三個數據,咱們須要創建一個 99999999 長度的 BitMap ,可是實際上只存了3個數據,這時候就有很大的空間浪費,碰到這種問題的話,能夠經過引入 Roaring BitMap 來解決。

算法比較成熟,所以參考的東西也挺多,就再也不列參考了。

Refer:

[0] 拜託,面試官別問我「布隆過濾器」了(修訂補充版)

https://bit.ly/2YHlKV4

[1] BitMap 的基本原理和實現

https://cloud.tencent.com/community/article/813907

[2] No.17【大數據算法】Bloom Filter 的數學背景

http://bit.ly/2gx6y84

[3] No.15【大數據算法】Bloom Filter 的基本原理和實現

http://bit.ly/2hYN5gT

[4] No.19 【大數據算法】Counting Bloom Filter 的原理和實現

http://bit.ly/2y02fNu

[5] 大數據計數原理1+0=1這你都不會算(八)No.60

http://bit.ly/2l7t64i

[6] 大數據分析經常使用去重算法分析『Bitmap 篇』

http://bit.ly/2ZLY2HR

相關文章
相關標籤/搜索