识别霍夫曼编码算法中的字符位置

时间:2012-05-23 16:07:30

标签: java algorithm compression huffman-code

我正在阅读霍夫曼编码算法来编码字符串。我可以看到字符的频率被考虑在一起构成一棵树。

以下是频率表:

a   b   d   e   f   h   i   k   n   o   r   s   t   u   v 
5   1   3   7   3   1   1   1   4   1   5   1   2   1   1   9

*space has frequency 9

我可以看到有一棵树。但我无法推导出如何在树中放置元素的规则。

这本书说所有频率较高的角色应该靠近根。但如果两个以上的字符具有相同的频率,那么它们必须位于根的不同侧。

问题是,我们如何决定立场?

在我的书a中有代码010r011e有代码100

有人可以帮忙吗?

2 个答案:

答案 0 :(得分:3)

你试过Wikipedia吗?有一个关于霍夫曼编码的很好的演示。算法很简单:你需要一个priority queue

算法有点像这样:

1. Create tree nodes with each character and their frequencies
2. Put all the letters and their frequencies in a priority queue Q
3. Do until Q contains only one element:
    3a. Pick two lowest-frequency items a, b
    3b. Create a tree node z with frequency(z) = frequency(a) + frequency(b)
    3c. Add a and b as left and right children of z
    3d. Put z in Q
4. Pick up the only element from Q. This would be the root of the tree.
5. Assign binary codes to each leaf node according to their root-to-leaf path.

优先级队列应设计为最小优先级队列,即频率最低的节点应首先出现。对于处理等频项目,使用一些其他标准(例如字母顺序)作为打破平局。与编码和解码的打破平衡标准保持一致。

答案 1 :(得分:2)

一旦你拥有你的树,那么它就是一个任意选择,分配0和1如何分配给道路上每个分叉的两个分支。因此,如果没有办法使该指派具有规范性,那么如何将比特分配给每个符号就没有“正确答案”,例如: r必须是011r可以是任何三位值。 (虽然这组频率的长度必须为3位。)

重要的是解码器获得与编码器相同的0和1分配。您可以直接发送代码,也可以发送长度并以规范方式分配0和1。例如,zip,gzip,png等中使用的压缩算法仅发送每个符号的位数。然后从最小长度开始,该长度的所有符号被分配从0开始的代码。符号按顺序分配代码,符号按其表示整数排序。例如。字符的ASCII排序顺序。对于下一个长度,在右侧添加位,并继续进行代码计数。这确保了正确的前缀码,从左到右解码。

所以在这种情况下,代码长度为:

2: _
3: a, e, r
4: d, f, n
5: b, h, t
6: i, k, o, s, u, v

所以我们得到(在每个长度内按字母顺序排列符号):

_: 00
a: 010
e: 011
r: 100
d: 1010
f: 1011
n: 1100
b: 11010
h: 11011
t: 11100
i: 111010
k: 111011
o: 111100
s: 111101
u: 111110
v: 111111

这里的比特分配与三本符号中的两个符号不同。作为其他完美的规范前缀代码选择的示例,您可以反转所有位,或者可以反转位列的任何子集。例如。你可以颠倒整个第一列。您可以更改每个长度中的符号顺序。您可以反转位顺序。实际上,zip等以相反的顺序存储上面显示的位,因此首先从最低有效位(即从右到左)进行解码。