編程珠璣-位向量

如何使用位邏輯運算(如與、或、移位)來實現位向量?

一、疑問

  • 什麼是位向量?

位向量(bit vector)就是由一些二進制位組成的向量。

例如,可以用如下字符串來表示集合{1, 2, 3, 5, 8, 13}
0 1 1 1 0 1 0 0 1 0 0 0 0 1 0 0 0 0 0 0
代表集合中數值的位置爲1,其他所有的位置都置爲0。

使用一個大數組,令N=1000000,若數組類型爲int,則數組定義爲int a[N/32+1]。
顯然a[0]可以表示0至31的整數,以此類推,a[i]可以表示32i至32(i+1)-1的整數。

  • 移位運算的幾個規則
m/2^n=m>>n
m%(2^n)=m&(2^n-1)
將變量a的第k位置1: a = ( a | (1 << k) )
將變量a的第k位清0: a = ( a & ~(1 << k) )

二、實現

#define BITSPERWORD 32      // 一個int數字32位
#define shift 5             // 2^5 = 32 用於判斷是第幾個32位int數
#define mask 0x1F           // 0b11111 , (2^5-1 = 31)
#define n 10000000          // 位向量元素個數
int a[1 + n / BITSPERWORD]; // 1 + n / BITSPERWORD = int數的個數;+1實現的進位制度

// 加入位向量
void set(int i)
{
    a[i >> shift] |= (1 << (i & mask));
    /*    
    i>>shift 等價於m/2^n=m>>n,即 i/32 。
    a類似一個二維數組,行是每一個int裏的每一個位列是a數組裏的每一個int。即判斷 i 映射到位向量裏的第幾個int裏。

    i & mask 等價於m%(2^n)=m&(2^n-1),即 i%32 。
    
    將變量a的第k位置1: a = ( a | (1 << k) )
    1<< (i & mask) 將 1 向左移動 i 後五位所表示的大小,也就是i在位上的位置,再或運算,將 i 映射在a[i /32 ]上的位置爲1
    */
}

void clr(int i)
{
	// 與set類似,將變量a的第k位清0: a = ( a & ~(1 << k) )
    a[i >> shift] &= ~(1 << (i & mask));
}

int test(int i)
{
    return a[i >> shift] & (1 << (i & mask));
}

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