天天看點

java zlib 位運算_位運算入門:找出一個二進制數的最右端的第一個1;計算一個二進制數中1的個數;找出數組中唯一一個出現次數為奇數的數;找出數組中唯二兩個出現次數為奇數的數...

位運算

異或操作也叫半加運算,其運算法則相當于不帶進位的二進制加法;

XOR 在英文裡面的定義為either one (is one), but not both;

異或的主要運用點:任何一個數和自身異或等于0,任何一個數和0異或等于0; 主要運用特性:

異或(^)操作時當且僅當兩個操作數不同時結果為1

與(&)操作時當且僅當兩個操作數都為1時結果為1 (是且是為是)

或(|)操作時隻要有一個操作數為1是結果為1

非(!)操作時就是取反

反(~)操作時按位取反

同或操作時當且僅當兩個操作數相同時結果為1(同或不常用)

算術左移(<

算術右移(>>)時将一個數的各二進制位全部右移若幹位,正數左補0,負數補1(即高位補符号位),右邊舍棄

位運算運用

1. 找出一個二進制數的最右端的第一個1

void findFirstRightOne(unsigned int num){

unsigned int first1R = num & ( (~num)+1 );

printf("%d 的最右端第一個1的十進制數是 %d \n",num,first1R);

}

2. 計算一個二進制數中1的個數

void bit1count(int num){

int cnt = 0;

int tmp = num;

while(tmp!=0){

//先找最後邊第一個1

int right1 = tmp & ( (~tmp)+1 );

++cnt;

//将原數和第一個1異或後,第一個1及其右邊所有的數都将為0

tmp ^= right1;

}

printf("%d 中二進制1的個數為 %d \n", num, cnt);

}

3. 找出數組中唯一一個出現次數為奇數的數

void findOnlyOneOddCountNumber(unsigned int len, int arr[]){

unsigned int i;

int xor = 0;

for(i=0;i

xor = xor ^ arr[i];

}

for(i=0;i

printf("%d ",arr[i]);

}

printf(" 中唯一一個出現次數為奇數次的數是 %d \n",xor);

}

void swapWithNoOtherVar(int *a,int *b){

printf("a:%d, b:%d 交換後為 ",*a,*b);

// 利用了兩個相同的數相異或時等于本身

*a = *a ^ *b;

// a ^ b ^ b = a => 将a的值給了b

*b = *a ^ *b;

// a ^ b ^ a(上一步中b的值已經改為a) = b => 将b的值給了a

*a = *a ^ *b;

printf("a:%d, b:%d \n",*a,*b);

}

4. 找出數組中唯二兩個出現次數為奇數的數

void findOnlyTwoOddCountNumber(unsigned int len, int arr[]){

unsigned int i;

//xor 的結果必然不為0

int xor = 0;

for(i=0;i

xor = xor ^ arr[i];

}

//先找到aor中最右的1 , right1中隻有一位是1,也就是這一位上one和two是不相等的

int right1 = xor & ( (~xor)+1 );

int one = 0;

for(i=0;i

//如果數組中某個數和right1相與不為0,則該數在right1的1的位上的數也為1

//這個操作實際上是将arr分為2組,一組是在right1的1的位上的數也為1,反之為另一組

//因為one和two是不相等的則他們一定在兩個不同的分組

if(arr[i] & right1 != 0){

//這一步配合循環找到該組中唯一一個出現次數為奇數的數

one ^= arr[i];

}

}

//利用 swapWithNoOtherVar 相同的原理得到另外一個數

// xor = one ^ tow ; two = one ^ two ^ one = two

int two = xor ^ one;

for(i=0;i

printf("%d ",arr[i]);

}

printf(" 中唯二兩個出現次數為奇數次的數是 %d , %d \n",one,two);

}

5. 測試

//測試

int main (void){

{

printf("在不消耗額外空間的情況下交換兩個數的值\n");

int a=123,b=321;

swapWithNoOtherVar(&a,&b);

}

//--------------------------

int i;

{

printf("-----找出一個二進制數的最右端的第一個1\n");

for(i=0;i<4;i++){

findFirstRightOne(i);

}

}

//--------------------------

{

printf("-----計算一個二進制數中1的個數\n");

bit1count(123);

}

//--------------------------

{

printf("-----找出數組中唯一一個出現次數為奇數的數\n");

int arr[9];

for(i=1;i<=8;i++){

if(i%2==0) arr[i] = arr[i-1];

else arr[i] = i;

}

arr[0]=111;

findOnlyOneOddCountNumber(9,arr);

}

//--------------------------

{

printf("-----找出數組中唯二兩個出現次數為奇數的數\n");

int arr[10];

for(i=1;i<=8;i++){

if(i%2==0) arr[i] = arr[i-1];

else arr[i] = i;

}

arr[0]=111;arr[9]=112;

findOnlyTwoOddCountNumber(10,arr);

}

return 0;

}

/*

在不消耗額外空間的情況下交換兩個數的值

a:123, b:321 交換後為 a:321, b:123

-----找出一個二進制數的最右端的第一個1

0 的最右端第一個1的十進制數是 0

1 的最右端第一個1的十進制數是 1

2 的最右端第一個1的十進制數是 2

3 的最右端第一個1的十進制數是 1

-----計算一個二進制數中1的個數

123 中二進制1的個數為 6

-----找出數組中唯一一個出現次數為奇數的數

111 1 1 3 3 5 5 7 7 中唯一一個出現次數為奇數次的數是 111

-----找出數組中唯二兩個出現次數為奇數的數

111 1 1 3 3 5 5 7 7 112 中唯二兩個出現次數為奇數次的數是 111 , 112

/*