我们可以看到,Human 树的建立方法就保证了,出现次数多的符号,得到的 Human 编码位数少,
出现次数少的符号,得到的 Human 编码位数多。
各个符号的 Human 编码的长度不一,也就是变长编码。对于变长编码,可能会遇到一个问题,就是重
新编码的文件中可能会无法如区分这些编码。
比如,a 的编码为 000,b 的编码为 0001,c 的编码为 1,那么当遇到 0001 时,就不知道 0001 代表
ac,还是代表 b。出现这种问题的原因是 a 的编码是 b 的编码的前缀。
由于 Human 编码为根结点到叶子结点路径上的 0 和 1 的序列,而一个叶子结点的路径不可能是另一个
叶子结点路径的前缀,所以一个 Human 编码不可能为另一个 Human 编码的前缀,这就保证了
Human 编码是可以区分的。
1.2.3 使用 Human 编码进行压缩和解压缩
为了在解压缩的时候,得到压缩时所使用的 Human 树,我们需要在压缩文件中,保存树的信息,也就
是保存每个符号的出现次数的信息。
压缩:
读文件,统计每个符号的出现次数。根据每个符号的出现次数,建立 Human 树,得到每个符号的
Human 编码。将每个符号的出现次数的信息保存在压缩文件中,将文件中的每个符号替换成它的
Human 编码,并输出。
解压缩:
得到保存在压缩文件中的,每个符号的出现次数的信息。根据每个符号的出现次数,建立 Human 树,
得到每个符号的 Human 编码。将压缩文件中的每个 Human 编码替换成它对应的符号,并输出。
2 gzip 所使用压缩算法的实现
我们将 gzip 的实现分成很多个部分,一个个来说明,这样做的原因见本文最后一部分。
gzip 中所使用的各种实现技巧的出处或者灵感,gzip 的作者在源码的注释中进行了说明。
2.1 寻找匹配串的实现
为一个串寻找匹配串需要进行大量的匹配工作,而且我们还需要为很多很多个串寻找匹配串。所以 gzip
在寻找匹配串的实现中使用哈希表来提高速度。
要达到的目标是,对于当前串,我们要在它之前的窗口中,寻找每一个匹配长度达到最小匹配的串,并找
出匹配长度最长的串。
在 gzip 中,最小匹配长度为 3,也就是说,两个串,最少要前 3 个字节相同,才能算作匹配。为什么最
小匹配长度为 3,将在后面说明。