目录

 

1 概述

2 LZ77算法原理

2.1 压缩

2.2 解压缩

3 Huffman编码

3.1 构造霍夫曼树

4 参考


1 概述

       DEFLATE是同时使用了LZ77算法与哈夫曼编码(Huffman Coding)的一个无损数据压缩算法。DEFLATE压缩与解代码可以在自由、通用的压缩库zlib上找到。常见的压缩算法如下:

  • zlib(RFC1950):一种格式,是对deflate进行了简单的封装,zlib = zlib头 + deflate编码的实际内容 + zlib
  • gzip(RFC1952):一种格式,也是对deflate进行的封装,gzip = gzip头 + deflate编码的实际内容 + gzip

2 LZ77算法原理

        LZ77算法是采用字典做数据压缩的算法,由以色列的两位大神Jacob Ziv与Abraham Lempel在1977年发表的论文《A Universal Algorithm for Sequential Data Compression》中提出。

       基于统计的数据压缩编码,比如Huffman编码,需要得到先验知识——信源的字符频率,然后进行压缩。但是在大多数情况下,这种先验知识是很难预先获得。因此,设计一种更为通用的数据压缩编码显得尤为重要。LZ77数据压缩算法应运而生,其核心思想:利用数据的重复结构信息来进行数据压缩。

       在具体实现中,用滑动窗口(Sliding Window)字典存储历史字符,Lookahead Buffer存储待压缩的字符,Cursor作为两者之间的 分隔,如图所示:

    并且字典与Lookahead Buffer的长度是固定的。 

2.1 压缩

用(p,l,c)表示Lookahead Buffer中字符串的最长匹配结果,其中

  • p表示最长匹配时,字典中字符开始时的位置(相对于Cursor位置),
  • l为最长匹配字符串的长度,
  • c指Lookahead Buffer最长匹配结束时的下一字符

压缩的过程,就是重复输出(p,l,c),并将Cursor移动至l+1,伪代码如下:

Repeat:
    Output (p,l,c),
    Cursor --> l+1
Until to the end of string

压缩示例如图所示:

2.2 解压缩

为了能保证正确解码,解压缩时的滑动窗口长度与压缩时一样。在解压缩,遇到(p,l,c)大致分为三类情况:

  • p==0且l==0,即初始情况,直接解码cc;
  • p>=l,解码为字典dict[p:p+l+1]
  • p<l,即出现循环编码,需要从左至右循环拼接,伪代码如下:
for(i = p, k = 0; k < length; i++, k++)
    out[cursor+k] = dict[i%cursor]

比如,dict=abcd,编码为(2,9,e),则解压缩为output=abcdcdcdcdcdce。

3 Huffman编码

       在传输电文时,每种字符出现的频率不同,想让电文在能够表达其意思的前提下尽可能短,自然需要让出现频率高的字符占的位数尽可能少。

3.1 构造霍夫曼树

      假如某一个文本只包含wuvxy等字符,如图对此进行如下构造过程:

  • 步骤一:统计文本的各权重分别为7,12,15,18,20
  • 步骤二:7,12,15,18,20选出权重最小的7、12进行构造生成19
  • 步骤三:19,15,18,20选出权重最小的15,18进行构造生成33
  • 步骤四:19,33,20选出权重最小的19,20进行构造生成39
  • 步骤五:33,39进行构造生成72

4 参考

1、【数据压缩】LZ77算法原理及实现

2、zlib-Deflate压缩算法

3、数据压缩算法---霍夫曼编码的分析与实现

4、详解Huffman压缩原理和c++代码实现

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐