如何使用位邏輯運算來實現位向量的理解

這是一道很是基礎的題目,考察對位運算的理解,好看題目只以爲好眼熟,而後(手賤)瞟了一眼答案,第一遍沒看明白答案的內容,就上網查了一下,網上的人要麼就是一筆帶過(大概是以爲太簡單),要麼就是誤人子弟。html

解決題目以前應該先搞清楚題目是幹嗎的:ios

位向量顧名思義就是用位來存儲一個數,文中說存儲N=10000000個數,每一位表明一個數。數組

咱們能夠定義一個int類型的數組int a[N],那麼若是a[9]的值爲1,則代表文件中存在一個值爲9。函數

這樣的話,咱們就能夠用一個數組來表示這麼多數。咱們又知道,一個int型的數有4個字節,也就是32位,那麼咱們能夠用N/32個int型數來表示這N個數:測試

a[0]表示第1~32個數(0~31)spa

a[1]表示第33~64個數(32~63)設計

code

這樣,每當輸入一個數字i,咱們應該先找到該數字在數組的第幾個元素中,也就是a[?],而後再肯定在這個元素的第幾位中。htm

舉個例子來講,好比輸入35,那麼35/32爲1餘3,則應該將a[1]的第4位置爲1。blog

好,有了上面的概念,能夠先來看看題中set是怎麼實現的:

void set(int i)
{
    a[i>>SHIFT] |= (1<<(i &MASK));
}

根據題目的要求,咱們不能夠用/運算符來設計程序,那除的話咱們能夠用右移來替代:

m>>n,表示m往右移動n位

輸入i,除以32至關於往右移動5位,則i>>SHIFT表明i/32獲得應該放在數組的第幾個元素中,而後要置相應的位置位1了:

先來看看1<<(i&MASK)是什麼意思。i&MASK至關於取i右移掉的部分,說白了就是取餘數。

好比35的二進制表示是:… 0010 0011

MASK的二進制是0001 1111

兩個相與操做獲得0 0011

而右移5位,移掉的數是0 0011,換算成10進制是3,正是餘數,與上面的操做值相等,都是0 0011。

所以1<<(i&MASK)就變成了1<<3,也就是將1右移3位,變成了1000。

而後在作一個|操做就將a[1]的第4位置1了。

對於clr函數,就是找到位置,而後清零

對於test函數,就是找到位置,作一個與操做,若是存在這個數,則返回1,不存在的話,由於是&操做,因此返回0。

下面是全部的答案:

#define BITSPERWORD 32
#define SHIFT 5
#define MASK 0x1F
#define N 10000000
int a[1+N/BITSPERWORD];
void set(int i)
{
    a[i>>SHIFT] |= (1<<(i &MASK));
}
void clr(int i )
{
    a[i>>SHIFT] &= ~(1<<(i &MASK));
}
int test(int i )
{

能夠寫一個main函數測試一下:

 

#include <iostream>//不要忘記它
using namespace std;//不要忘記它
int main(){
    int i = 35;
    //設置i,也就是置相應位置位1
    set(i);
    //測試是否置1了
    if(test(i))
        cout<<"ok"<<endl;
    return 0;
}

image

大概就這樣了。

(本文網址:http://www.cnblogs.com/marsdu/p/3181734.html

相關文章
相關標籤/搜索