判断32位整数二进制中1/0的个数

1
int findone(unsigned int n)
{
    for(int i = 0; n > 0; n >>=1)
    {
       i += (n & 1);
    }
    return i;
}

2.然而上述的算法,时间复杂度是T(m)=m,取决于二进制数的位数m。如果要求在更短时间内求出,应该如何做呢?
如果findone函数被反复调用(成千上万次调用),那应该怎么优化呢?

可以以空间换时间,构造一个表格,包含所有32位数中每一个中1的个数,直接索引就行了,但是这样的问题是空间占用大恐怖,不可取.但是可以分而治之,把32位数分成4份,构建一个256个元素的表格就行了.
const int one_in_char[256]=
{
     0, 1, 1, 2, 1, 2,2,3
......
                               ,8
}           //此方法可在UCOS II 中关于任务优先级相关代码中见到

int findone2(unsigned int n)
{
    unsigned char* ptr = (unsigned char*)&n;
    return one_in_char[ptr[0]] + one_in_char[ptr[1]] + one_in_char[ptr[2]] + one_in_char[ptr[3]];
}

3.一种更加巧妙的方法,貌似是MS面试题的答案
int findone3(unsigned int n)
{
    int count = 0;
    while(n > 0)
    {
       n &= (n -1);
       count++;
    }
    return count;
}           
4.一个看起来比较BT的算法
int    findone4(unsigned int n)
{
        x = (x & 0x55555555UL) + ((x >> 1) & 0x55555555UL); // 0 -2 in 2 bits
    x = (x & 0x33333333UL) + ((x >> 2) & 0x33333333UL); // 0-4 in 4 bits
#if 1
    // Version 1
    x = (x & 0x0f0f0f0fUL) + ((x >> 4) & 0x0f0f0f0fUL); // 0-8 in 8 bits
    x = (x & 0x00ff00ffUL) + ((x >> 8) & 0x00ff00ffUL); // 0-16 in 16 bits
    x = (x & 0x0000ffffUL) + ((x >> 16) & 0x0000ffffUL); // 0-31 in 32 bits
    return x;
#else
    // Version 2
    x = (x + (x >> 4)) & 0x0f0f0f0fUL; // 0-8 in 4 bits
    x += x >> 8; // 0-16 in 8 bits
    x += x >> 16; // 0-32 in 8 bits
    return x & 0xff;
#endif
}

posted on 2010-11-18 13:36  leesy  阅读(1030)  评论(0编辑  收藏  举报

导航