數據結構--位圖


先了解一下位運算的基礎知識:

所有比特的編號方法是:從低字節的低位比特位開始,第一個bit為0,最后一個bit為 n-1。

比如,給出一個數組:int[] array = new int[4]。那么:

a[0] -- a[4] 的比特位分別為:0--31,32--63,64--95,96--127

下面我們依據一個程序探究數組比特位的編號:

public class BitNumber {
    public static void main(String[] args) {
        int[] array = new int[4];
        for (int i = 0; i < array.length; i++) {
            array[i] = 16;
        }
        for (int i = 0; i < array.length; i++) {
            array[i] = array[i] >> 4;
            System.out.println(array[i]);
        }
    }
}

結果是輸出了4個1,也就是說剛開始比特位編排為:0000 0000 0001 0000,使用位運算,使其右移了4位,變為:0000 0000 0000 0001.

 

利用位運算& 進行取模

位運算跟取模運算之間聯系微妙,具體可從下面的例子中看出來:

100%32;100&31

上述公式的結果是一樣的,讓我們探究一下他們的原理:

100%32 的取余運算,將取到一百減去3個32之后的余數為4。 100&31是進行按位與運算,31=0001 1111;100=0110 0100,當他們進行按位與時,大於等於32的那部分將給消去,留下的便是余數。

當然上述運算成立的條件便是 32對應位置的數必須是2的N次冪。

 

特定位的設置與清除

假如現在 int a = 0; 現在a的編碼全部為0,現在要將其從右往左第5個位置設置為1,然后再清除上述操作

static int a = 0;
    public static void main(String[] args) {
        a |= (1<<5);     // | 按位或操作 ,雙目運算符 a = a|(1<<5);
        System.out.println(a);
        a &= ~(1<<5);    // & 按位與操作,雙目運算符, ~ 按位非操作,單目運算符
        System.out.println(a);
    }

上述運算的結果分別為32 0.

 

字節位置與位位置

 一個int是4個字節,每個字節有32bit,我們可以將數據存儲在這些位內。比如我們要存儲100這個數,我們只需在位置100存儲一個1。將第100位置為1,也就是說最少需要有100個位置,每個位置1bit,100個位置需要12.5字節,因為一個int型是4字節,所以我們需要定義一個數組 int[4]。

現在我們要對這個數組的100位進行操作,首先要知道100在這個數組中的第幾個元素,每個數組元素都是32位,那么100所在的位置就是100/32,也就是 100>>5。然后在元素中的位置也就是:100%32,也就是100&31,也就是100&0x1F。

給一個例子:

給40億個不重復的unsigned int的整數,沒有排過序,然后再給一個數,如果快速判斷這個數是否在那40億個數當中。

因為unsigned int數據的最大范圍在在40億左右(需要40億bit),40*10^8/1024*1024*8=476,因此只需申請512M的內存空間,每個bit位表示一個unsigned int。讀入40億個數,並設置相應的bit位為1.然后讀取要查詢的數,查看該bit是否為1,是1則存在,否則不存在。

 

參考:程珠璣-位圖數據結構

 


免責聲明!

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



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