【发布时间】:2014-07-10 03:43:07
【问题描述】:
我目前正在进行哈夫曼文本压缩练习,但我在标题编码方面遇到了一些问题。我使用 字符频率表 将我需要的信息保存为标题用于文件的解压(全部转换成二进制字符串,然后保存在字节数组中)。
所以一开始,我为每个字符使用 2 个字节,为字符使用 1 个字节,为它的频率使用 1 个字节。但是我意识到它不适用于某些字符的频率可能超过 255(1byte) 的大文本。
因此我进行了修改,我根据每个字符的频率调整了保留字节。它看起来像这样:
public String freString(int freq, String s){
freq = freq - 255;
s = s + ("11111111");
if(freq>=255){
s = freString(freq,s);
}else{
String remainFreq= Integer.toBinaryString(freq);
//patch the ommited zeros of last byte
remainFreq= String.format("%8s", remainFreq);
remainFreq= tempString.replace(' ', '0');
s = s + remainFreq;
}
return s;
}
这样,在解压过程中,我会查看下一个字节的值,如果是 255,则继续添加下一个字节的值……等等。
我的标题示例:
[ 9 , 141, 3, 142, 255, 33, 143, 255, 255, 2 ]
[我的标头长度 = 9 ,a = 3, b = 288, c = 512]
它运行良好,但随着文本越来越大,它大大降低了我的压缩率。 例如:如果“a”重复 5000 次。我将最多使用 20 字节 来存储我的频率值字符串,而不是 2 字节 (00010011 10001000 = 5000)
所以这是我的问题......我可以使用更好的策略来动态增加字符的保留字节并同时指示“频率字符串的结尾”吗?我虽然为每个字符保留至少 3 个字节(1 个用于 char,1 个用于其频率,1 表示频率字符串的结尾),但这会影响较小文本文件的压缩率。 这是我必须采取的权衡吗?还是有更好的方法?
【问题讨论】:
-
你设置保存频率了吗?保存符号长度是最常见的(通常需要在空间不大的情况下使用技巧)。
-
您是否需要标头中的实际频率,或者仅足以重新创建用于编码的树?您只有 256 个(最多)不同的频率,(不出所料)可以放入一个字节;你能把实际频率映射到这个更小的空间吗?
-
@ScottHunter 我不确定...因为要重建与以前完全相同的二叉树,我需要每个字符的确切频率,如果我错了,请纠正我
-
@harold 我不确定你所说的符号长度是什么意思。你能解释一下吗?
-
每个符号都有一个长度,以位为单位。另请参阅canonical Huffman code。和practical Huffman coding。如果你愿意,我可以在答案中详细解释。如果您只想更有效地存储频率,我建议称重每个字节 - 将第二个字节乘以 256,将第三个字节乘以 65536,依此类推。您还可以为每个字节保留一个位以指示它是否是最后一个(显然会更改权重)。
标签: algorithm text binary compression huffman-code