种群计数-位计数
前言:
这是一篇位运算相关的文章,问题只有一个,统计一个数,它的2进制表示中1的个数。
这道题大家应该都见过,《编程之美-微软技术面试心得》一书中有相关的章节。
不说废话~
正题来了:
算法一:
1 count = 0; 2 for(i = 0;i < 32;i++) 3 { 4 if(x&1) count ++; 5 x = x >> 1; 6 }
对整数2进制表示的每一位进行位&运算,判断是否为1,是的话计数器count+1;
算法二:
1 count = 0; 2 for(i = 0;i < 32;i++) 3 { 4 count += (x & 1); 5 x = x >> 1; 6 }
算法二是对算法一的优化,少了if的判断,还是渣;
算法三:
1 count = 0; 2 while(x) 3 { 4 count ++; 5 x = x & (x-1); 6 }
这是个好算法:x&(x-1),析出x最右边的1;
每循环一次相当于x的二进制表示最右边的1变成了0;
直到x的值为0,代表所有的1都析出;
算法四:
1 int count = 0; 2 int size[] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4}; 3 while(x) 4 { 5 count += size[x&0xF]; 6 x = x>>4; 7 }
采用查表法,每4位一查,效率也是很快的;
算法五:(重头戏)
1 x = (x & 0x55555555) + ((x >> 1) & 0x55555555) 2 x = (x & 0x33333333) + ((x >> 2) & 0x33333333) 3 x = (x & 0x0F0F0F0F) + ((x >> 4) & 0x0F0F0F0F0F) 4 x = (x & 0x00FF00FF) + ((x >> 8) & 0x00FF00FF) 5 x = (x & 0x0000FFFF) + ((x >> 16) & 0x0000FFFF)
最后的x值为1的个数;
这是一个“分治”策略的例子,在原始问题上(对32个位求和)被分成两个问题(对16个位求和),递归运用这一策略,直到对1个位求和;
后记:
还有问题的请研究《高效程序的奥秘》
一本致力于位运算的好书