[Data Structure] Bit-map空間壓縮和快速排序去重


  Bit-map是一種很巧妙的數據存儲結構。所謂的Bit-map就是用一個bit位來標記某個元素對應的Value,而Key即是該元素。由於采用了Bit為單位來存儲數據,可以大大節省存儲空間。Bit-map在實際中也有着廣泛的應用,比如快速排序,元素去重以及空間縮減等等。本文通過Bit-map的幾個應用實例對Bit-map以及其擴展結構Bloom Filter進行介紹。

1. Bit-map的基本思想

  32位機器上,對於一個整型數,比如int a=1 在內存中占32bit位,這是為了方便計算機的運算。但是對於某些應用場景而言,這屬於一種巨大的浪費,因為我們可以用對應的32bit位對應存儲十進制的0-31個數,而這就是Bit-map的基本思想。Bit-map算法利用這種思想處理大量數據的排序、查詢以及去重。

2. 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)|(0x01<<(i%8)) 當然了這里的操作涉及到Big-ending和Little-ending的情況,這里默認為Big-ending),因為是從零開始的,所以要把第五位置為一(如下圖):

  

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

 

  然后我們現在遍歷一遍Bit區域,將該位是一的位的編號輸出(2,3,4,5,7),這樣就達到了排序的目的,時間復雜度O(n)。

  Bit-map用於排序的優缺點同樣明顯。

  優點:

  1.運算效率高,不需要進行比較和移位;

  2.占用內存少,比如N=10000000;只需占用內存為N/8=1250000Byte=1.25M。 

  缺點:

  所有的數據不能重復。即不可對重復的數據進行排序和查找。    

3. Bit-map應用之快速去重

  這是經常會在面試中出現的問題。比如,2.5億個整數中找出不重復的整數的個數,內存空間不足以容納這2.5億個整數。 

  首先,根據“內存空間不足以容納這2.5億個整數”我們可以快速的聯想到Bit-map。下邊關鍵的問題就是怎么設計我們的Bit-map來表示這2.5億個數字的狀態了。其實這個問題很簡單,一個數字的狀態只有三種,分別為不存在,只有一個,有重復。因此,我們只需要2bits就可以對一個數字的狀態進行存儲了,假設我們設定一個數字不存在為00,存在一次01,存在兩次及其以上為11。那我們大概需要存儲空間幾十兆左右。

  接下來的任務就是遍歷一次這2.5億個數字,如果對應的狀態位為00,則將其變為01;如果對應的狀態位為01,則將其變為11;如果為11,,對應的轉態位保持不變。

  最后,我們將狀態位為01的進行統計,就得到了不重復的數字個數,時間復雜度為O(n)。

4. Bit-map應用之快速查詢

  同樣,我們利用Bit-map也可以進行快速查詢,這種情況下對於一個數字只需要一個bit位就可以了,0表示不存在,1表示存在。假設上述的題目改為,如何快速判斷一個數字是夠存在於上述的2.5億個數字集合中。

  同之前一樣,首先我們先對所有的數字進行一次遍歷,然后將相應的轉態位改為1。遍歷完以后就是查詢,由於我們的Bit-map采取的是連續存儲(整型數組形式,一個數組元素對應32bits),我們實際上是采用了一種分桶的思想。一個數組元素可以存儲32個狀態位,那將待查詢的數字除以32,定位到對應的數組元素(桶),然后再求余(%32),就可以定位到相應的狀態位。如果為1,則代表改數字存在;否則,該數字不存在。

5. Bit-map擴展——Bloom Filter

  Bloom Filter:一種空間效率很高的隨機數據結構,它利用位數組很簡潔地表示一個集合,並能判斷一個元素是否屬於這個集合。

  Bloom Filter的這種高效是有一定代價的:在判斷一個元素是否屬於某個集合時,有可能會把不屬於這個集合的元素誤認為屬於這個集合(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。

6. 總結

  使用Bit-map的思想,我們可以將存儲空間進行壓縮,而且可以對數字進行快速排序、去重和查詢的操作。Bloom Fliter是Bit-map思想的一種擴展,它可以在允許低錯誤率的場景下,大大地進行空間壓縮,是一種拿錯誤率換取空間的數據結構。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM