几个常见的压缩算法

再学习了haffman算法以后发现压缩算法颇有意思,上网查了点资料,这是作好的一篇(主要是我能理解)。前面几种都能看懂,关键是那个LZ77算法。这个是很强大的压缩算法,zip,rar用得都是这种算法,让咱们来感叹下两个犹太人的强大!!!算法

 

几个常见的压缩算法(转)

(一) 字典算法
字典算法是最为简单的压缩算法之一。它是把文本中出现频率比较多的单词或词汇组合作成一个对应的字典列表,并用特殊代码来表示这个单词或词汇。例如:
有字典列表:
00=Chinese
01=People
02=China
源文本:I am a Chinese people,I am from China 压缩后的编码为:I am a 00 01,I am from 02。压缩编码后的长度显著缩小,这样的编码在SLG游戏等专有名词比较多的游戏中比较容易出现,好比《SD高达》。数组

(二) 固定位长算法(Fixed Bit Length Packing)
这种算法是把文本用须要的最少的位来进行压缩编码。
比 如八个十六进制数:1,2,3,4,5,6,7,8。转换为二进制为:00000001,00000010,00000011,00000100, 00000101,00000110,00000111,00001000。每一个数只用到了低4位,而高4位没有用到(全为0),所以对低4位进行压缩编 码后获得:0001,0010,0011,0100,0101,0110,0111,1000。而后补充为字节获得:00010010, 00110100,01010110,01111000。因此原来的八个十六进制数缩短了一半,获得4个十六进制数:12,34,56,78。
这也是比较常见的压缩算法之一。缓存

(三) RLE算法
这种压缩编码是一种变长的编码,RLE根据文本不一样的具体状况会有不一样的压缩编码变体与之相适应,以产生更大的压缩比率。学习

  变体1:重复次数+字符
文本字符串:A A A B B B C C C C D D D D,编码后获得:3 A 3 B 4 C 4 D。网站

  变体2:特殊字符+重复次数+字符
文本字符串:A A A A A B C C C C B C C C,编码后获得:B B 5 A B B 4 C B B 3 C。编码串的最开始说明特殊字符B,之后B后面跟着的数字就表示出重复的次数。编码

  变体3:把文本每一个字节分组成块,每一个字符最多重复 127 次。每一个块以一个特殊字节开头。那个特殊字节的第 7 位若是被置位,那么剩下的7位数值就是后面的字符的重复次数。若是第 7 位没有被置位,那么剩下 7 位就是后面没有被压缩的字符的数量。例如:文本字符串:A A A A A B C D E F F F。编码后获得:85 A 4 B C D E 83 F(85H= 10000101B、4H= 00000100B、83H= 10000011B)游戏

  以上3种不RLE变体是最经常使用的几种,其余还有不少不少变体算法,这些算法在Winzip Winrar这些软件中也是常常用到的。ip

(四) LZ77算法
LZ77算法是由 Lempel-Ziv 在1977发明的,也是GBA内置的压缩算法。LZ77算法有许多派生算法(这里面包括 LZSS算法)。它们的算法原理上基本都相同,不管是哪一种派生算法,LZ77算法总会包含一个动态窗口(Sliding Window)和一个预读缓冲器(Read Ahead Buffer)。动态窗口是个历史缓冲器,它被用来存放输入流的前n个字节的有关信息。一个动态窗口的数据范围能够从 0K 到 64K,而LZSS算法使用了一个4K的动态窗口。预读缓冲器是与动态窗口相对应的,它被用来存放输入流的前n个字节,预读缓冲器的大小一般在0 – 258 之间。这个算法就是基于这些创建的。用下n个字节填充预读缓存器(这里的n是预读缓存器的大小)。在动态窗口中寻找与预读缓冲器中的最匹配的数据,若是匹 配的数据长度大于最小匹配长度 (一般取决于编码器,以及动态窗口的大小,好比一个4K的动态窗口,它的最小匹配长度就是2),那么就输出一对〈长度(length),距离 (distance)〉数组。长度(length)是匹配的数据长度,而距离(distance)说明了在输入流中向后多少字节这个匹配数据能够被找到。字符串

  例如:(假设一个 10个字节的动态窗口, 以及一个5个字节的预读缓冲器)
文本:A A A A A A A A A A A B A B A A A A A
--------------------- =========
动态窗口 预读缓存器
动 态窗口中包含10个A ,这就是最后读取的10个字节。预读缓冲器包含了 B A B A A。编码的第一步就是寻找动态窗口与预读缓存器类似长度大于2的字节部分。在动态窗口中找不到B A B A A,因此B就被按照字面输出。而后动态窗口滑过1个字节,如今暂时输出了一个B。
第二步:A A A A A A A A A A A B A B A A A A A
--------------------- =========
动态窗口 预读缓存器
现 在预读缓冲器包含A B A A A,而后再和动态窗口进行比较。这时,在动态窗口找到了类似长度为2的A B,所以一对〈长度, 距离〉就被输出了。长度(length)是2 而且向后距离也是2,因此输出为<2,2>,而后动态窗口滑过2个字节。如今已经输出了B <2,2>。
第三步:A A A A A A A A A A A B A B A A A A A
--------------------- =========
动态窗口 预读缓存器
继续上面的方法获得输出结果<5,8>。如今已经输出了B <2,2> <5,8>。
最终的编码结果是:A A A A A A A A A A A B <2,2> <5,8>。
但 数组是没法直接用二进制来表示的,LZ77会把编码每八个数分红一组,每组前用一个前缀标示来讲明这八个数的属性。好比数据流:A B A C A C B A C A按照LZ77的算法编码为:A B A C<2,2> <4,5>,恰好八个数。按照LZ77的规则,用“0”表示原文输出,“1”表示数组输出。因此这段编码就表示为:00001111B(等于 0FH),所以获得完整的压缩编码表示:F A B A C 2 2 4 5。虽然表面上只缩短了1个字节的空间,但当数据流很长的时候就会突出它的优点,这种算法在zip格式中是常常用到。it

  除此以外还有不少压缩算法,像霍夫曼编码(Huffman Encoding)等等。这些编码也是很是的著名并且压缩效率极高,不过这些编码的算法相对比较繁琐,规则也很复杂,因为篇幅就不逐一介绍了。若是你们对这方面感兴趣能够到网站相关网站查询资料。

相关文章
相关标签/搜索