Excellent algorithms use a lot of place operations, and bit operations are rarely used in the work, with an example, we have a look at its advantages and principles, by the way mark a wave of common bit operations.

Last article “interesting binary” we talked about some basic knowledge of binary, but did not talk about the operation in place, some students shout not enough, that this article mainly explains the use of the next bit operation, or from an example, I hope to inspire you. Remember the following example application please mark, help a lot.

A, sudoku

Sudoku is a good example to introduce bit operation. There is a big difference in efficiency between using bit operation and not using it. Let’s start with sudoku requirements:

1. The current number contains 1 to 9 and is not repeated

2. The number in the current column contains 1 to 9 and does not repeat

3. The numbers in the house where the current number is located (i.e. the big grid of 3×3) all contain 1-9 and are not repeated (the house is one in each thick line as shown below).

,

1. General algorithm

If we use the conventional method, every time we fill in a number, we need to check whether there are repeated numbers in the current row, column and other positions in the palace. In extreme cases, we need to cycle 27 (3*9) times to check. Let’s take a look at the check under the conventional algorithm

Int sp (int sp) {// check(int sp) {// return 1 intfg= 0;if(!fg) fg= check1(sp, startH[sp], addH) ; // Check if there are the same numbers in the same columnif(!fg) fg= check1(sp, startV[sp], addV) ; // Check if the peer has the same numberif(!fg) fg= check1(sp, startB[sp], addB) ; // Check if there are the same numbers as the nine squaresreturn(fg); } int check1(int sp, int start, int *addnum)fg= 0, i, sp1 ; / / of all evilforcyclefor(i=0; i<9; i++) {
	      sp1= start+ addnum[i] ;
	      if(sp! =sp1 && sudoku[sp]==sudoku[sp1])fg++ ;
	   }
	   return(fg); }Copy the code

Is this efficiency scary? Every time you fill in one, you need to check27 times. Is there an algorithm for checking once? Of course we do. We do it in bits, all at once. Let’s look at the idea of the next bit operation:

2. Bit operation



As shown in the figure above, a single row (or column or house) of data has a total of 9 digits from 1 to 9, which are collectively referred to as nine house numbers. If we use binary, with nine digits as the bit coordinates of binary data, using nine bits of binary can be corresponding to one and one, there is data in the bit, identified as 1, no data identified as 0, so a positive number can solve a row of nine data states, without the need to save an array.

For example, if you look at the dark red part of the figure, the current nine houses of data already have 1 and 3, then the first and third digits from the right of the binary are identified as 1, a number 5 can store the current row (or column, house) array state, if the number is 511, it indicates that all the nine houses of digits are used up, as shown in the first row.

Check To check whether a number is already in use, you can take a bit operation to get the k-th right bit of the binary to check whether it is 1. If 1, the specified number is already in use. Let’s look at the specific check algorithm:

// sp is the current position index, indexV row index, indexH column index, Int check(int sp,int indexV,int indexH,int indexB) {int sp,int indexV,int indexH,int indexB Return 1 if have used int status = statusV [indexV] | statusH [indexH] | statusB [indexB]; // All 9 numbers are usedif (status>=STATUS_MAX_VALUE)
		{
			return1; } int number=sudoku[sp]; // Select the KTH bit from the right, if 1 indicates that the value already existsreturn status>>(number-1)&1;
	}Copy the code

Int markStatus(int indexV,int indexH,int indexB,int number){if (number<1)
		{
			return0; } / / put the right number of the first k (counting from 1) into 1 statusV [indexV] | = (1 < < (number 1)); statusH[indexH]|=(1<<(number-1)); statusB[indexB]|=(1<<(number-1)); }Copy the code


How do we get the number that can be filled in at the current position using the following legend position






You can see that two bits solves the problem of checking the available numbers, whereas the conventional algorithm required 27 lookups to get them. Of course, this algorithm can also be optimized, such as the use of heuristic DFS, search available numbers, faster, you can click here.

Conventional algorithm and bit operation algorithm C language code, I have uploaded the code cloud, want to know click the following link, go to view. (Regular algorithm Google)

Address: general algorithm Sudoku, bit version Sudoku


Second, the basic

1. Bit operators

symbol meaning The rules
& with When both bits are 1, the result is 1
| or If one of the bits is 1, the result is 1
^ Exclusive or 0 and 1 neither xor 0 is the same, xor 1 is the opposite
~ The not Take the opposite of 0 and 1
<< Shift to the left The bits are all moved to the left by several bits, the high bits are discarded, and the low bits are filled with 0
>> Arithmetic moves to the right All the bits are shifted several bits to the right, and the value of k most significant bits is supplemented by the high position
>> Logic moves to the right The bits are all shifted to the right by several bits, and the high position is filled with 0

Note:

1. Bitwise operations apply only to integers, not to floats and doubles.

2, in addition to the logical right shift symbol is not the same as various languages, such as Java is >>>.

3. Bitwise operators have a lower precedence, so use parentheses to ensure the order of operations. For example, 1& I +1 executes I +1 before &.


3. Application examples

Great application example, you can mark it, convenient to use in the future.

1. Mixture

Bit operation instance

An operation function The sample
x >> 1 Get rid of the last one 101101 – > 10110
x << 1 Add a 0 at the end 101101 – > 1011010
x << 1 | 1 Add a 1 at the end 101101 – > 1011011
x | 1 Make the last digit a 1 101100 – > 101101
x & -2 Let’s make the last digit a 0 101101 – > 101100
x ^ 1 Let’s take the last digit backwards 101101 – > 101100
x | (1 << (k-1)) Change the KTH right digit to 1 101001->101101,k=3
x & ~ (1 << (k-1)) Change the KTH right digit to 0 101101->101001,k=3
x ^(1 <<(k-1)) The KTH right digit is the opposite 101001->101101,k=3
x & 7 Take at the end of the three 1101101 – > 101
x & (1 << k-1) At the end of the k bit 1101101->1101,k=5
x >> (k-1) & 1 Take the KTH bit from the right 1101101->1,k=4
x | ((1 << k)-1) Let’s change the last k bit to 1 101001->101111,k=4
x ^ (1 << k-1) The last k bit is reversed 101001->100110,k=4
x & (x+1) Turn the consecutive ones on the right into zeros 100101111 – > 100100000
x | (x+1) Make the first 0 from the right a 1 100101111 – > 100111111
x | (x-1) Turn the successive zeros on the right into ones 11011000 – > 11011111
(x ^ (x+1)) >> 1 Take the consecutive 1’s on the right-hand side 100101111 – > 1111
x & -x Get rid of the left side of the first 1 from the right 100101000 – > 1000
x&0x7F Take at the end of the seven 100101000 – > 101000
x& ~0x7F No Less than 127 001111111 & ~0x7F->0
x & 1 Judge parity 00000111 & 1 – > 1

2. Switch two numbers

int swap(int a, int b)  
{  
    if (a != b)  
    {  
        a ^= b;  
        b ^= a;  
        a ^= b;  
    }  
}  Copy the code


3. Find the absolute value

int abs(int a)  
{  
    int i = a >> 31;  
    return ((a ^ i) - i);  
}  Copy the code


Binary search 32-bit integer leading 0 number

int nlz(unsigned x)
{
   int n;

   if (x == 0) return(32);
   n = 1;
   if((x >> 16) == 0) {n = n +16; x = x <<16; }if((x >> 24) == 0) {n = n + 8; x = x << 8; }if((x >> 28) == 0) {n = n + 4; x = x << 4; }if((x >> 30) == 0) {n = n + 2; x = x << 2; } n = n - (x >> 31);return n;
}Copy the code


5, binary reverse order

int reverse_order(int n){

  n = ((n & 0xAAAAAAAA) >> 1) | ((n & 0x55555555) << 1);
  n = ((n & 0xCCCCCCCC) >> 2) | ((n & 0x33333333) << 2);
  n = ((n & 0xF0F0F0F0) >> 4) | ((n & 0x0F0F0F0F) << 4);
  n = ((n & 0xFF00FF00) >> 8) | ((n & 0x00FF00FF) << 8);
  n = ((n & 0xFFFF0000) >> 16) | ((n & 0x0000FFFF) << 16);

  return n;
}Copy the code



6. The number of ones in binary

unsigned int BitCount_e(unsigned int value) { unsigned int count = 0; // 11 01 00 10 = 01 01 00 00 00 + 10 00 00 00 10, // Value = 11 01 00 10, high_v = 01 01 00 00, low_v = 10 00 00 10 // then value = high_v + low_v, High_v_1 = high_v >> 1 = high_v / 2 / value = high_v_1 + high_v_1 + low_v Value = value & 0x55555555 + (value >> 1) &0x55555555; value = value - ((value >> 1) & 0x55555555); Value = (value & 0x33333333) + ((value >> 2) & 0x33333333); value = (value & 0x0f0f0f0f) + ((value >> 4) & 0x0f0f0f0f); value = (value & 0x00ff00ff) + ((value >> 4) & 0x00ff00ff); value = (value & 0x0000ffff) + ((value >> 8) & 0x0000ffff);returnvalue; //value = (value & 0x55555555) + (value >> 1) &0x55555555; //value = (value & 0x33333333) + ((value >> 2) & 0x33333333); //value = (value & 0x0f0f0f0f) + ((value >> 4) & 0x0f0f0f0f); //value = value + (value >> 8); //value = value + (value >> 16); //return (value & 0x0000003f);
    }Copy the code



———————–end————————-

Big size, pay attention to personal growth and technical learning, hope to use their own little change, can give you some inspiration

Scan for more.