8

我目前正在尝试使用非常简单的前序遍历算法为霍夫曼树构建查找表,但我在执行非常基本的位操作时遇到了困难。伪代码如下:

void preOrder(huffNode *node, int bit) //not sure how to represent bit
{
  if (node == NULL)
    return;

  (1) bit = bit + 0; //I basically want to add a 0 onto this number (01 would go to 010)
  preOrder(node->getLeft(), bit);
  (2) bit = bit - 0 + 1; //This should subtract the last 0 and add a 1 (010 would go to 011)
  preOrder(node->getRight());


}

我对如何执行第 (1) 行和第 (2) 行定义的操作感到非常困惑

使用什么数据类型来表示和打印二进制数?在上面的示例中,我将数字表示为 int,但我很确定这是不正确的。另外,您如何添加或减去值?我明白 & 和 | 类型逻辑有效,但我对如何在代码中执行这些类型的操作感到困惑。

任何人都可以发布一些非常简单的例子吗?

4

3 回答 3

8

这是二进制操作的一些基本示例。我在这里主要使用就地操作。

int bit = 0x02;   //               0010
bit |= 1;         // OR  0001 ->   0011
bit ^= 1;         // XOR 0001 ->   0010
bit ^= 7;         // XOR 0111 ->   0101
bit &= 14;        // AND 1110 ->   0100
bit <<= 1;        // LSHIFT 1 ->   1000
bit >>= 2;        // RSHIFT 2 ->   0010
bit = ~bit;       // COMPLEMENT -> 1101

如果你想打印一个二进制数,你需要自己做......这是一种效率稍低但可读性适中的方法:

char bitstr[33] = {0};
for( int b = 0; b < 32; b++ ) {
    if( bit & (1 << (31-b)) )
        bitstr[b] = '1';
    else
        bitstr[b] = '0';
}
printf( "%s\n", bitstr );

[编辑]如果我想要更快的代码,我可能会预先生成(或硬编码)一个查找表,其中包含 0-255 的所有数字的 8 位序列。

// This turns a 32-bit integer into a binary string.
char lookup[256][9] = {
    "00000000",
    "00000001",
    "00000010",
    "00000011",
    // ... etc (you don't want to do this by hand)
    "11111111"
};

char * lolo = lookup[val & 0xff];
char * lohi = lookup[(val>>8) & 0xff];
char * hilo = lookup[(val>>16) & 0xff];
char * hihi = lookup[(val>>24) & 0xff];

// This part is maybe a bit lazy =)
char bitstr[33];
sprintf( "%s%s%s%s", hihi, hilo, lohi, lolo );

相反,您可以这样做:

char *bits = bitstr;
while( *hihi ) *bits++ = *hihi++;
while( *hilo ) *bits++ = *hilo++;
while( *lohi ) *bits++ = *lohi++;
while( *lolo ) *bits++ = *lolo++;
*bits = 0;

或者只是展开整个事情。;-)

char bitstr[33] = {
    hihi[0], hihi[1], hihi[2], hihi[3], hihi[4], hihi[5], hihi[6], hihi[7],
    hilo[0], hilo[1], hilo[2], hilo[3], hilo[4], hilo[5], hilo[6], hilo[7],
    lohi[0], lohi[1], lohi[2], lohi[3], lohi[4], lohi[5], lohi[6], lohi[7],
    lolo[0], lolo[1], lolo[2], lolo[3], lolo[4], lolo[5], lolo[6], lolo[7],
    0 };

当然,查找中的那 8 个字节与 64 位整数的长度相同……那么这个呢?比在字符数组中毫无意义地蜿蜒曲折要快得多。

char bitstr[33];
__int64 * intbits = (__int64*)bitstr;
intbits[0] = *(__int64*)lookup[(val >> 24) & 0xff];
intbits[1] = *(__int64*)lookup[(val >> 16) & 0xff];
intbits[2] = *(__int64*)lookup[(val >> 8) & 0xff];
intbits[3] = *(__int64*)lookup[val & 0xff];
bitstr[32] = 0;

自然,在上面的代码中,您会将查找值表示为 int64 而不是字符串。

无论如何,只是指出您可以编写它但是适合您的目的。如果您需要优化,事情会变得有趣,但对于大多数实际应用程序而言,此类优化可以忽略不计或毫无意义。

于 2012-07-30T00:40:36.897 回答
4

除非您的二进制序列比 int 中的位数更长,否则您可以只使用 int。

要将 0 添加到 a 的当前表示的末尾,可以使用 << 1

要将 a 的当前表示形式末尾的 0 替换为 1,您可以使用 a ^= 1

请注意,要以这种方式使用 int,您还需要跟踪您的位在 int 中从哪里开始,以便如果您有例如值 0x0,您可以知道 0、00、000 中的哪一个,... 。 它是。

于 2012-07-30T00:32:46.937 回答
2

代码中的操作:

(1) bit = bit << 1;
(2) bit = bit|1;

但是,您还必须保持序列的长度。

如果 int 的长度对您来说足够好,那么没有理由不使用它。但是,在霍夫曼算法中,它实际上取决于数据。C++ 程序员应该对任意长度的位序列使用 boost::dynamic_bitset。它还支持上面的位操作。http://www.boost.org/doc/libs/1_42_0/libs/dynamic_bitset/dynamic_bitset.html

于 2012-07-30T00:47:53.243 回答