【压缩原理】 deflate 算法
目录1 概述2 LZ77算法原理2.1 压缩2.2 解压缩3 Huffman编码3.1 构造霍夫曼树4 参考1 概述DEFLATE是同时使用了LZ77算法与哈夫曼编码(Huffman Coding)的一个无损数据压缩算法。DEFLATE压缩与解代码可以在自由、通用的压缩库zlib上找到。常见的压缩算法如下:zlib(RFC1950):一种...
目录
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 参考
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)