在C++中紧凑地保存一个Huffman树



假设我已经用压缩文件对霍夫曼树进行了编码。因此,我有一个示例文件输出:

001A1C01E01B1D

我在将此字符串逐点保存到文件时遇到问题。我知道C++一次只能向文件输出一个字节,所以我在用字节存储这个字符串时遇到了问题。是否可以将前三位转换为char,而不需要将程序填充为字节?如果它为遍历代码填充了一个字节,那么我的树(和代码)将完全混乱。如果我一次把它砍掉一个字节,那么如果树不是8的倍数,会发生什么?如果压缩文件的位长度不是8的倍数,会发生什么?

希望我已经足够清楚了。

这个问题的标准解决方案是填充。有许多可能的填充方案。填充方案最多填充偶数个字节(即8比特的倍数)。此外,它们以比特为单位对消息的长度进行编码,或者对填充比特的数量进行编码(可以通过减法来确定以比特为单元的消息长度)。后一种解决方案显然会产生稍微更有效的填充。

最简单的是,您可以将最后一个字节中"未使用"的位数附加为额外的字节值。

向上一级,首先假设填充位的数量适合3位。定义编码文件的最后3位,以对填充位的数量进行编码。现在,如果消息占用的最后一个字节不超过5位,那么填充可以很好地放在同一个字节中。如果需要添加一个字节来包含填充,则最大间隙为5+2=7(来自额外字节的未使用高位的5,2是最后一个字节中可能的最大可用空间,否则3位填充值将适合该值)。由于0-7可以用3位表示,所以这是有效的(它不适用于2位,因为最大间隙更大,可表示值的范围更小)。

顺便说一句,将填充信息放在文件末尾(而不是作为文件开头的头)的主要优点之一是,压缩函数可以对流进行操作,而不必事先知道其长度。解压缩也可以是基于流的,并仔细处理EOF信号。

只需将n字节的序列视为8nbit的序列。使用>><<|&运算符从可变长度位代码序列中汇编字节。

正确处理流的末尾很重要。你需要一个流结束代码,这样解码器就知道要停止,而不是试图解码完成最后一个字节的最后填充位。

最新更新