BitMap算法

先看一個場景:如何判斷一個數是否在40億個整數中?

題目:給一臺普通PC,2G內存。我有40億個整數,再給一個新的整數,我需要判斷新的整數是否在40億個整數中,你會怎麼做?

分析:

40億個int佔(40億*4字節)/1024/1024/1024 大概爲16G左右,很明顯內存只有2G,放不下,因此不可能將這40億數據放到內存中計算。要快速的解決這個問題最好的方案就是將數據擱內存了,所以現在的問題就在如何在2G內存空間以內存儲着40億整數。

判斷一個數是否存在,其實只有兩個狀態,存在或者不存在,可以用一個位代表。這樣我就申請40億個位就好了,新的數轉換成一個位,然後判斷一下這個位是0還是1就行了。其實你可以想想,32位int的範圍,總共就是2的32次方,大概42億多點。所以你可以申請2的32次方個位。算一下需要多少內存呢?2的32次方個位,相當於2的29次方個字節,哇,才500MB,真是節省了不少內存呢。

BitMap思想:

一個byte是佔8個bit,如果每一個bit的值就是有或者沒有,也就是二進制的0或者1,如果用bit的位置代表數組值有還是沒有,那麼0代表該數值沒有出現過,1代表該數組值出現過。不也能描述數據了嗎?如下圖:

再看代碼之前,我們先搞清楚一個問題,一個數怎麼快速定位它的索引號,也就是說搞清楚byte[index]的index是多少,position是哪一位。舉個例子吧,例如add(14)。14已經超出byte[0]的映射範圍,在byte[1]範圍之類。那麼怎麼快速定位它的索引呢。如果找到它的索引號,又怎麼定位它的位置呢。Index(N)代表N的索引號,Position(N)代表N的所在的位置號。

Index(N) = N/8 = N >> 3;

Position(N) = N%8 = N & 0x07;

基於上面的分析,我們寫一個簡單的BitMap的算法如下:
 

package bitmap;

public class BitMap {

	 //保存數據的 
	private byte[] bits;
	//能夠存儲多少數據
	private int capacity;
	
	public BitMap(int capacity){
		this.capacity = capacity;
		//1bit能存儲8個數據,那麼capacity數據需要多少個bit呢,capacity/8+1,右移3位相當於除以8
		bits = new byte[(capacity >>3 )+1];
		}
	
	public void add(int num){
		// num/8得到byte[]的index
		int arrayIndex = num >> 3;
		// num%8得到在byte[index]的位置
		int position = num & 0x07;
		//將1左移position後,那個位置自然就是1,然後和以前的數據做|,這樣,那個位置就替換成1了。
		bits[arrayIndex] |= 1 << position;
		}
	
	public boolean contain(int num){
		// num/8得到byte[]的index
		int arrayIndex = num >> 3;
		// num%8得到在byte[index]的位置
		int position = num & 0x07;
		//將1左移position後,那個位置自然就是1,然後和以前的數據做&,判斷是否爲0即可
		return (bits[arrayIndex] & (1 << position)) !=0;
		}

	public void clear(int num){
		// num/8得到byte[]的index
		int arrayIndex = num >> 3;
		// num%8得到在byte[index]的位置
		int position = num & 0x07;
		//將1左移position後,那個位置自然就是1,然後對取反,再與當前值做&,即可清除當前的位置了.
		bits[arrayIndex] &= ~(1 << position);
	}
	

	public static void main(String[] args) {
		BitMap bitmap = new BitMap(100);
		bitmap.add(7);
		System.out.println("插入7成功");

		boolean isexsit = bitmap.contain(7);
		System.out.println("7是否存在:"+isexsit);

		bitmap.clear(7);
		isexsit = bitmap.contain(7);
		System.out.println("7是否存在:"+isexsit);

	}

}

 

 

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