霍夫曼编码 - 标头和 EOF

LDM*_*M91 3 algorithm encoding header huffman-code eof

我目前正在致力于在 Java 中实现基于霍夫曼算法的程序,并且我正处于需要将编码内容输出到文件的阶段。我对如何实现解码所需的标头和 eof 有点困惑。对于目前的标题,我拥有输入文件中出现的所有唯一值及其频率,但在一些文章中,我看到人们用 0 或 1 表示节点,然后是频率(我有点困惑) by 因为它没有说明符号是什么)。

另外,对于我所理解的 EOF,我像符号一样对其进行编码,以便读取和解码,但是我不确定我可以使用什么值来肯定不会出现?我知道它的权重需要为 1,但不确定如何确保它实际上不在文件中。

man*_*nge 5

我不得不为一项任务这样做一次,这就是我们使用的方法。

通过使用 0 和 1 对树的结构(而不​​是频率)进行编码来对标头进行编码。“0”表示沿着树移动,“1”表示我们在叶节点。这导致了对树进行了一种前序遍历,对其进行了唯一编码。

例如,像 (((ab) c) (de)) 这样的树将被编码为“0001 a1 b1 c01 d1 e”,其中 a,b,c,d,e 是它们的 ASCII 形式。

这是图形形式的树:

     / \
   /\   /\
 /\  c d  e
a  b 
Run Code Online (Sandbox Code Playgroud)

对于 EOF,我们使用文件中的最后 3 位来指定需要读取的最后两个字节的数量。一旦我们读取了最后一个字节(所以我们正在处理倒数第二个字节),我们检查了最后 3 位:他们编码了要读取的更多位,减去 6。这110101xxxxxxx000意味着“读取110101(6 位)并丢弃其他所有内容”。1101011xxxxxx001表示“读取1101011(7 位)并丢弃其余部分”等。

这样做意味着我们不必有一个特殊的值来表示 EOF,我们仍然可以一次读取一个字节的文件(尽管我们实际上需要在我们工作的位置之前读取一个字节)。

(对于 EOF,我没有读过你的文章,所以我不知道我们的想法是否适用于你的方法。)