统计二进制1个数
1. 循環移位
要注意x>>1并不改變x的值,要x >>=1
2.刪除最右端的1(對于稀疏1)
x = x&(x-1) (譬如,0110,經過上式運算變為0100)
同理,x &=(x+1)刪除最右邊的0?
3. 查表
static int bits_in_char [256] = {??????????
????0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2,
????3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3,
????3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3,
????4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4,
????3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5,
????6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4,
????4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5,
????6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5,
????3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3,
????4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6,
6, 7, 6, 7, 7, 8
};
?? int bitcount (unsigned int n) ?? { ????? // works only for 32-bit ints ??? return bits_in_char [n???????? & 0xffu] ????????? + bits_in_char [(n >> 8) & 0xffu] ????????? + bits_in_char [(n >> 16) & 0xffu] ????????? + bits_in_char [(n >> 24) & 0xffu] ; ?? }使用靜態數組表,列出所有8bit(256個)無符號數含有Bit1的個數。將32Bit?的n分4部分,直接在表中找到對應的Bit1的個數,然后求和。
這是最快的方法了。缺點是需要比較大的內存。
也可以通過強制轉換指針,對n分段
unsigned char *p = (unsigned char *)&n;
p[0],p[1],p[2],p[3]
4.?
位加法,舉例說明,考慮2位整數 n=11,里邊有2個1,先提取里邊的偶數位10,奇數位01,把偶數位右移1位,然后與奇數位相加,因為每對奇偶位相加的和不會超過“兩位”,所以結果中每兩位保存著數n中1的個數;相應的如果n是四位整數 n=0111,先以“一位”為單位做奇偶位提取,然后偶數位移位(右移1位),相加;再以“兩位”為單位做奇偶提取,偶數位移位(這時就需要移2位),相加,因為此時沒對奇偶位的和不會超過“四位”,所以結果中保存著n中1的個數,依次類推可以得出更多位n的算法。整個思想類似分治法。
例如:32位無符號數的1的個數可以這樣數:
int count_bits(unsigned long n)
{
????//0xAAAAAAAA,0x55555555分別是以“1位”為單位提取奇偶位
??? n = ((n & 0xAAAAAAAA) >> 1) + (n & 0x55555555);
??? //0xCCCCCCCC,0x33333333分別是以“2位”為單位提取奇偶位
??? n = ((n & 0xCCCCCCCC) >> 2)?+ (n & 0x33333333);
??? //0xF0F0F0F0,0x0F0F0F0F分別是以“4位”為單位提取奇偶位
??? n = ((n & 0xF0F0F0F0) >> 4) + (n & 0x0F0F0F0F);
????//0xFF00FF00,0x00FF00FF分別是以“8位”為單位提取奇偶位
??? n = ((n & 0xFF00FF00) >> 8) + (n & 0x00FF00FF);
??? //0xFFFF0000,0x0000FFFF分別是以“16位”為單位提取奇偶位
??? n = ((n & 0xFFFF0000) >> 16) + (n & 0x0000FFFF);
??? return n;
}
總結
- 上一篇: 线性时间查找固定频率的元素
- 下一篇: 有向图强连通分量tarjan算法