2011-11-20 90 views
1

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

另外,对于EOF,据我了解,我将它编码为符号,因此它被读取和解码,但是我不确定我可以使用它的什么值,肯定不会出现?我知道它需要1的权重,但不确定如何确保它实际上不在文件中。

+0

什么文章?你能提供一些链接吗? – svick

+0

我考虑的主要两个是http://michael.dipperstein.com/huffman/和http://www.cs.duke.edu/csed/poop/huff/info/想到我可以看到的标题为什么他们现在这样做我想(使用头文件构造一个树,然后通过读取文件内容来获取频率?目前我的头文件中有符号和频率,这是错误的)这只是伪代码我是困惑,因为我不知道该如何使用它,因为这不可能代码可能已经在树中的符号? – LDM91

回答

2

我必须这样做一次作业,这是我们使用的方法。

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

例如,就像一棵树(((AB)C)(DE))将被编码为 “0001 ”,其中a,b,C,d,e为他们的ASCII形式。

这里的图形形式的树:

/\ 
    /\ /\ 
/\ c d e 
a b 

对于我们所使用的文件中的最后3位指定多少所需的最后两个字节的要读的EOF。一旦我们读到最后一个字节(因此我们正在处理第二个最后一个字节),我们检查了最后3位:它们编码了多少位读取,减去6.因此110101xxxxxxx000意思是“读取110101(6位)并放弃其他所有内容”。 1101011xxxxxx001意味着“读1101011(7位)和丢弃其他”等

这样做,这样意味着我们没有必须有一个特殊的值表示的EOF,我们仍然可以在读取文件字节时间(尽管我们实际上需要在我们工作的地方之前阅读一个字节)。

(对于EOF我没有看过你的文章,所以我不知道我们的想法与你的方法工作。)

+0

我想我已经开始更好地理解头文件了,但是您能否再澄清一下这个例子?我不确定我是否正确阅读树,是否:根节点,然后是超级节点与另一个超级节点里面的A + B离开和一个C离开节点(在超级节点内部持有A + B的外部),那么另一个有D和E的超级节点会离开?如果是这样,那么“0001a1b1c”是否表示在你读完了你假设的下一个假期之后的两片叶子? – LDM91

+0

我已经添加了一些树的更直观的表示,所以我希望有所帮助。你知道你放置树叶的位置,它总是位于最左边的位置,所以下一个最左边的位置就是下一个“位”的操作位置。 000 - >向左下分支,1 - >将a放在当前位置,并移动到下一个最左边的非叶节点等。 – mange

2

霍夫曼编码指定如何从一串字符创建哈夫曼树和那么如何将它编码为一系列位。

它没有指定你应该如何对树进行编码,或者如何确定要读取多少位。确切的位数是一个问题,因为您只能将整个字节保存到文件中。所以你需要一些方法来确切地确定在哪一点结束。

对于编码树,有几个选项。其中一个是记录每个字符的计数并让解码器从中重建树。其他选项是以某种方式直接对树进行编码,例如使用0-1方法(我假设您提到的文章)描述。

然后有adaptive Huffman coding它根本不需要树,但更复杂。

为了决定何时结束,您可以在文件中写入字符的总数,然后使用它来决定何时停止。或者,如果您使用字符计数对树进行编码,则可以免费获得此计数。

另一种选择是使用EOF字符。这是霍夫曼树中的一个字符,但不会编码任何正常值。您可以将其想象为第257个值,假设您正在编码字节。 (你可能使用EOF标记的一些正常值,如零字节,但这需要你绝对确定它不会出现在输入文件中。)

+0

感谢您的回复我认为我现在可以做EOF,但是感谢总计数建议(可以不相信我没有想到它!),如果它没有。 – LDM91

+0

@svick我知道这个角色必须具有大于256的值,但如果它不是ASCII字符,我会如何将它放入文件中? –

+0

@C_B与其他字符一样:通过在树中对其位置进行编码。 – svick