Gzip是Linux下的压缩软件,.gz后缀的文件就是经gzip压缩后的文件。Gzip的源码当然由压缩和解压缩两部分构成,但本文只打算介绍其压缩部分,这部分的代码风格良好,且注释充分,并能很好的体现所用到的算法,而解压的代码完全是没有注释的一坨,其解压思路我们大致可以根据压缩过程反向推理出来,所以就不管它了。
目录
一、算法介绍
二、实现介绍
……
一、Gzip中涉及的压缩算法简介:
1、游程编码(run length encoding)
这是一种非常直观的编码。一个例子就能说明:
一串数字5555557777733322221111111
经游程编码后变为(5,6)(7,5)(3,3)(2,4)(1,7)
不难发现,在一个括号中,第二个数字表示第一个数字重复的次数。
显然,这种编码方式,对字符连续出现次数很多的串,压缩效果很好。但对于字符不连续出现的串,哪怕出现的频率非常高,也无能为力。
2、LZ77编码
这是由名叫Lempel和Ziv的两个人在1977年提出的算法,所以被叫做LZ77算法。这种编码也很简单。一个例子:
这样一个字符串2B or not 2B, that is the Q.
经LZ77编码后变为2B or not (10, 2), that is the Q.
发现第二个2B被(10, 2)替换掉了,(10, 2)是一个距离-长度二元组,代表的意思是重复10个字符之前长度为2的串,数一下,发现果然就是2B。
显然,这种编码方式,对文本的压缩效果会很好,因为像英文中the啊and啊这些词经常出现。
3、哈弗曼编码
这个算法教科书中都有介绍。网上找了一篇很不错的介绍文章http://www.thecodeway.com/blog/?p=870
简单的说就是,根据字符在串中出现的频率,对字符的进行重新编码,在原编码和新编码之间建立一种一一映射,使出现频率较高的字符新编码较短,而出现频率低的字符新编码较长,这样就使得用新编码构成的串比原来短了。
不同于上面两种编码,经哈弗曼编码后的串,已经完全脱胎换骨,需要额外地保存新旧编码的一一映射关系,才能还原原字符串,即解压缩。
至于gzip如何把这几种算法融合起来,且听下文分解。