最近几天在一直在忙于一个H5小应用的更改,一直没有时间来继续研究我们在课堂上实现的这一些压缩算法。今天好不容易抽出时间来,一定要把这个曾经的落下的重新捡起来并且完善。
我们知道在原来很多的编码当中,我们对字符串进行压缩,对文件进行压缩等绝大多数都需要我们预先对整个字符串和整个文件中的数据的分布有一些大致的了解,也就是说,我们在压缩之前就差不多了解这个文件中的基本的字符都有哪些,大致出现的频率是怎样的等。这种算法我个人认为还有有点不足,正是因为我们需要对整个文件里的数据有个整体的了解,对于这些算法我们在进行那些不易知道文件内容的文件就显得比较不太好进行了。但是字典编码在这些不了解文件的基础上我们也能够进行比较高效的压缩,那么接下来我们就来看看,字典编码的发展、原理以及代码实现。
字典编码本质上就是利用我们从头开始,然后将在字典中出现过的字符串使用一个索引值代替,以此来达到压缩目的。
一、历史
以色列两位大神Ziv和Lempel于1977年发表题为“顺序数据压缩的一个通用算法(A Universal Algorithm for Sequential Data Compression )”的论文,论文中描述的算法被后人称为LZ77算法。
次年,这两位搭档对他们的算法进行改进,并发表了该论文的续篇“通过可变比率编码的 立序列的压缩(Compression of Individual Sequences via Variable Rate Coding)”,描述了后来被命名为LZ78的压缩算法。
1984年,T. A. Welch 发表了名为“高性能数据压缩技术( A Technique for High Performance Data Compression )”的论文,描述了他在Sperry研究中心的研究成果,这是LZ78算法的一个变种,也就是后来非常有名的LZW算法。1990年后,T.C.Bell等人又陆续提出了许多LZ系列算法的变体或改进版本。
……
二、原理
从以上的历史我们可以看到啊,字典算法事实上包含很多很多中不同的算法,在这里我们选择最原始的LZ77以及LZ78这两个算法最为重点进行研究,后来的LZW算法就直接是LZ78的变体,原理基本上都是相似的,只要LZ78能够完全实现,那么实现LZW起来也比较容易了。
(一)LZ77算法
A、压缩编码原理
可能有好多人会好奇为什么叫LZ77算法,从以上的历史阶段我们大致应该了解了,这个算法是由ziv和Lempel两位大神一起在1977年研究出的,因此我们取名LZ77算法,简单粗暴,深入人心。
好啦,废话不多说了。我们直接来看看LZ77就行是怎样在进行数据的压缩:
事实上在LZ77算法中,整体思路是,我们先手动设定一个窗口,这个窗口包含两个部分,其中之一是位于左半部分的字典区域,另一个是位于窗口右端的待编码区。
大致上就是这样的:
然后我们在这个窗口内,将待编码区中出现的字符串在字典区进行查找,以此来达到压缩的目的。
LZ77算法的输出是一个三元组,(off, len, char)分别表示是匹配字符串的偏移(在这里的偏移实际上可以有两种,第一种是匹配字符串离字典区左边的距离,第二种是匹配字符串离字典区右边的距离,我更加习惯使用第二种),第二个len是表示匹配字符的长度,第三个则是表示匹配之后的下一个字符。
这样说起来可能还是有点抽象,我们在这里用一个实例说明一下流程:
我们以字符串aacaacabcabaaac
先来看看LZ77压缩算法是怎样进行压缩和解压缩的——
因为我们在LZ77中我们的字典事实上是动态生成的,而且随着窗口长度的不同而具有不同的字典,因此我们刚开始进行编码的时候我们的字典为空。
我们在进行算法之前,需要进行一些