位运算有很大的妙用,在C语言中发扬光大。有什么做用呢?在数据结构和算法中有个很重要的概念就是:时间和空间。位运算就能够提升时间的效率和空间的利用率。算法
没有什么神奇之处,只是以紧凑的二进制格式来描述数据结构,应用之多举不胜举。记住,最小的存储单元是bit而不是byte数据结构
根本缘由是读取内存次数少,咱们知道CPU一次读取内存的最大字节数和字长有关,正是由于把数据压缩在有限的数据结构中,读取内存的次数大大减小。数据结构和算法
一、如何不使用中间变量,交换两个变量? ide
a = a ^ b; b = a ^ b; a = a ^ b;
可能会有人说使用加减法也能够,如:测试
a = a + b; b = a - b; a = a - b;
可是加减法是有反作用的,容易致使数据溢出。spa
二、状态的改变,咱们可能常常写相似下面的代码:内存
if (b) { b = false; } else { b = true; }
或者更精简一点get
b = b ? false : true;
但依然会别扭,由于你要改变一个标志的状态,首先要知道原有状态,使用位运算能够避免it
b ^= b;
三、位向量,不少底层库中都有位向量的类,可用于不少场合,高效环保。我本身写了一个位向量,求解1亿一下素数,时间不到3秒,内存占用不到13M,可见位运算的威力。io
#define LONG_BIT_LENGTH sizeof(long) #define BIT_SHIFT_UNIT (LONG_BIT_LENGTH/8 + 1) #define BIT_MASK (LONG_BIT_LENGTH-1) //位向量结构:方便同时使用多个位向量 typedef struct tag_bit_vector { long *bit_buffer; //数据区 long max_bit_num; //总bit数 }TBitVector; //======================================================================================== //分配一个位向量 TBitVector *mallc_bit_vector(long bit_max) { TBitVector *pbit_vector = 0; pbit_vector = (TBitVector *)malloc(sizeof(TBitVector)); if (pbit_vector == NULL) return NULL; pbit_vector->bit_buffer = (long *)calloc(LONG_BIT_LENGTH, (bit_max + BIT_MASK) >> BIT_SHIFT_UNIT); if (pbit_vector->bit_buffer == NULL) return NULL; pbit_vector->max_bit_num = bit_max; return pbit_vector; } //释放一个位向量 void free_bit_vector(TBitVector *bit_vector) { free(bit_vector->bit_buffer); free(bit_vector); } //======================================================================================== //设置 void set_bit_vector(TBitVector *bit_vector, long idx) { if (idx >= bit_vector->max_bit_num) return; bit_vector->bit_buffer[idx >> BIT_SHIFT_UNIT] |= 1 << (idx & BIT_MASK); } //清除 void cls_bit_vector(TBitVector *bit_vector, long idx) { if (idx >= bit_vector->max_bit_num) return; bit_vector->bit_buffer[idx >> BIT_SHIFT_UNIT] &= ~(1 << (idx & BIT_MASK)); } //探测 int test_bit(TBitVector *bit_vector, long idx) { if (idx >= bit_vector->max_bit_num) return 0; return bit_vector->bit_buffer[idx >> BIT_SHIFT_UNIT] & (1 << (idx & BIT_MASK)); }
求解素数代码:
int sievePrime(TBitVector *pBitVerctor, unsigned long prime) { unsigned long i; if (prime*prime >= pBitVerctor->max_bit_num) { return 0; } for (i=prime<<1; i<pBitVerctor->max_bit_num; i+=prime) { set_bit_vector(pBitVerctor, i); } return -1; } //测试 #define PRIME_NUMBER_MAX 100000000 int main(int argc, char *argv[]) { int milisection = 0; int i = 0; int primeCount = 0; struct timeval start; struct timeval end; TBitVector *pdata = mallc_bit_vector(PRIME_NUMBER_MAX); milisection = GetTickCount(&start); for (i=2; i<PRIME_NUMBER_MAX; i++) { if (test_bit(pdata, i)) continue; if (sievePrime(pdata, i) == 0) { break; } } GetTickCount(&end); printf("times : %d\n", (end.tv_sec * 1000 * 1000 + end.tv_usec) - (start.tv_sec * 1000 * 1000 + start.tv_usec)); free_bit_vector(pdata); getchar(); return 0; }
总结: 位运算应用场景还有不少,要想用好,主要看你的抽象能力。如今是大内存和多核时代,没有必要时也不建议使用,除非用在密集运算或须要高效率的算法上。