网工干货知识

超全学习笔记
当前位置:首页 > 干货知识

LZW(Lempel–Ziv–Welch)压缩技术

更新时间:2026年03月27日   作者:spoto   标签(Tag):

为什么我们需要压缩算法呢?

压缩技术可以分为两类:有损压缩和无损压缩。 虽然这两种方法使用的压缩技术各不相同,但它们的目标都是相同的:在图形数据中查找重复的数据(LZW算法用于GIF格式),并采用更紧凑的数据表示方式。 无损压缩通过识别并消除统计上的冗余性,从而减少了所需的位数。 在无损压缩过程中,没有任何信息会被丢失。 另一方面,有损压缩通过去除那些不必要或不太重要的信息来减少比特数。 因此,我们需要数据压缩,主要是因为:

  • 未压缩的数据会占用大量的存储空间,这对于空间有限的硬盘以及较慢的互联网下载速度来说并不理想。
  • 虽然硬件的性能越来越好,成本也不断降低,但那些能够减少数据容量的算法同样有助于技术的不断发展。
  • 例如,一分钟未经压缩的高清视频数据量可以超过1GB。那么,如何将两小时的视频内容存储在25GB的蓝光光盘上呢?


有损压缩方法包括DCT(离散余弦变换)、向量量化以及变换编码等。而无损压缩方法则包括RLE(运行长度编码)、字符串表压缩、LZW(Lempel-Ziff-Welch算法)以及zlib等。虽然存在多种压缩算法,但我们这里主要讨论LZW算法。

Lempel–Ziv–Welch(LZW)算法是什么?

LZW算法是一种非常常用的压缩技术。这种算法通常用于GIF格式的文件压缩,同时也可以用于PDF和TIFF格式的文件压缩。在Unix系统中,还有“compress”命令也使用这种算法来进行文件压缩。这种压缩方式属于无损压缩方式,也就是说,在压缩过程中不会丢失任何数据。该算法的实现方式非常简单,而且在硬件上可以实现很高的压缩效率。LZW算法也是被广泛使用的Unix文件压缩工具“compress”所使用的算法,因此也被用于GIF图像格式的压缩。
该算法依靠重复的模式来节省数据存储空间。由于其简单性和灵活性,LZW成为最常用的数据压缩技术。许多声称能够“使硬盘容量翻倍”的电脑工具,其实都是基于LZW技术的。

它是如何工作的呢?

LZW压缩的原理是:首先读取一系列符号,将这些符号组合成字符串,然后再将这些字符串转换为编码。由于这些编码所占用的空间比原来的字符串要小,因此就能实现压缩效果。LZW的特点包括:

  • LZW压缩算法使用了一个编码表。通常情况下,该编码表的条目数量为4096个。编码表中,0到255之间的数字被用来表示输入文件中单个字节的数据。
  • 在编码过程中,代码表只包含前256个条目,其余的条目则被留空。通过使用256到4095之间的代码来表示字节序列,从而实现压缩效果。
  • 在编码过程中,LZW会识别出数据中重复出现的序列,并将这些序列添加到代码表中。
  • 解码的过程是:首先,从压缩文件中取出每一个编码,然后将其与代码表进行匹配,从而确定该编码所代表的字符或字符组合。

例如:ASCII码。 通常,每个字符都由8个二进制位来表示,这样就能容纳最多256种不同的符号。 该算法试图将库中的字符位数从9位扩展到12位。 这些新的独特符号,是由之前在字符串中出现过的符号组合而成的。 它并不总是能够很好地进行压缩处理,尤其是当字符串长度较短且结构复杂时。 不过,这种方法对于压缩冗余数据来说非常有效。而且,不需要在保存数据时同时存储新的词典信息。因此,这种方法来处理数据时,既能够压缩数据,也能够解压数据。
已经有一些很不错的文章被写出来了。你可以在这里进一步阅读这些文章。另外,Mark Nelson的文章也相当不错。

实施/执行

该压缩算法的原理如下:在处理输入数据的过程中,会使用一个字典来记录那些出现频率最高的单词与对应的编码值之间的对应关系。这样,输入文件中的单词就会被替换为相应的编码值,从而实现数据的压缩。因此,当输入数据中包含大量重复出现的长单词时,该算法的效率也会随之提高。

LZW编码

  *     PSEUDOCODE
  1     Initialize table with single character strings
  2     P = first input character
  3     WHILE not end of input stream
  4          C = next input character
  5          IF P + C is in the string table
  6            P = P + C
  7          ELSE
  8            output the code for P
  9          add P + C to the string table
  10           P = C
  11         END WHILE
  12    output code for P 


请测试下面的代码:
 


输出:
 


此外,还可以查看由Mark Nelson所编写的、采用C++风格的代码。这里还有6种不同的实现方式。另外,RosettaCode还列出了用不同语言实现的LZW压缩算法的几种方法。

使用LZW算法进行压缩

示例1:使用LZW算法来压缩该字符串:巴巴阿阿阿 
下面这个图表详细展示了整个流程的步骤。

LZW解压缩

LZW解压缩器在解压缩过程中会创建相同的字符串表。它从前256个表项开始,这些表项被初始化为单个字符。对于输入流中的每个字符来说,除了第一个字符之外,其余的字符都会更新相应的字符串表。解码过程是通过读取这些代码,并将它们转换为已构建好的代码表来实现的。

LZW解压算法

*    PSEUDOCODE
1    Initialize table with single character strings
2    OLD = first input code
3    output translation of OLD
4    WHILE not end of input stream
5        NEW = next input code
6        IF NEW is not in the string table
7               S = translation of OLD
8               S = S + C
9       ELSE
10              S = translation of NEW
11       output S
12       C = first character of S
13       OLD + C to the string table
14       OLD = NEW
15   END WHILE


示例2:LZW解压缩:使用LZW工具来解压如下输出序列:<66><65><256><257><65><260> 
下面所示的步骤顺序非常清晰。

在这个例子中,72位的数据被表示为72位的数据。在构建了合理的字符串表之后,压缩效果会显著改善。
LZW总结:该算法能够很好地压缩重复的数据序列。由于每个码字由12位组成,因此,任何单个编码后的字符都会使数据大小增加,而不是减少。

用于LZW压缩的C++代码,包括编码和解码过程,如下所示:

C++
#include<bits/stdc++.h>使用命名空间标准;向量<整数>编码(字符串s1){cout<<编码\n";无序映射<字符串,整数>表格/列表;为了(整数i=0;i<=255;i++){字符串ch="";ch+=字符/字母(i);表格/列表[ch]=i;}字符串p="",c="";p+=s1[0];整数代码=256;向量<整数>输出代码;cout<<字符串\t输出代码\t加法\n";为了(整数i=0;i<s1.长度();i++){if(i!=s1.长度()-1)c+=s1[i+1];if(表格/列表.找到(p+c)!=表格/列表.结束()){p=p+c;}否则{cout<<p<<"\t"<<表格/列表[p]<<"\t\t"<<p+c<<"\t"<<代码<<结束;输出代码.push_back(表格/列表[p]);表格/列表[p+c]=代码;代码++;p=c;}c="";}cout<<p<<"\t"<<表格/列表[p]<<结束;输出代码.push_back(表格/列表[p]);返回输出代码;}无效/无意义解码(向量<整数>op){cout<<"\n解码\n";无序映射<整数,字符串>表格/列表;为了(整数i=0;i<=255;i++){字符串ch="";ch+=字符/字母(i);表格/列表[i]=ch;}整数旧的/老旧的=op[0],n;字符串s=表格/列表[旧/老的];字符串c="";c+=s[0];cout<<s;整数计数=256;为了(整数i=0;i<op.尺寸/大小()-1;i++){n=op[i+1];if(表格/列表.找到(n)==表格/列表.结束()){s=表格/列表[旧的/老化的];s=s+c;}否则{s=表格/列表[n];}cout<<s;c="";c+=s[0];表格/列表[计数]=表格/列表[旧的/老旧的]+c;计数++;旧的/老旧的=n;}}整数主要/核心(){字符串s=“WYS*WYGWYS*WYSWYSG”;向量<整数>输出代码=编码(s);cout<<输出代码为:“”;为了(整数i=0;i<输出代码.尺寸/大小();i++){cout<<输出代码[i]<<“”;}cout<<结束;解码(输出代码);}

输出结果: 
Encoding
String    Output_Code    Addition
W    87        WY    256
Y    89        YS    257
S    83        S*    258
*    42        *W    259
WY    256        WYG    260
G    71        GW    261
WY    256        WYS    262
S*    258        S*W    263
WYS    262        WYSW    264
WYS    262        WYSG    265
G    71
Output Codes are: 87 89 83 42 256 71 256 258 262 262 71 

Decoding
WYS*WYGWYS*WYSWYSG

 

LZW相比其他方法的优势在于:哈夫曼: 

  • LZW不需要任何关于输入数据流的先验信息。
  • LZW能够一次性压缩输入流。
  • LZW的另一个优点就是其简单性,这使得其处理速度非常快。

高压缩比:LZW能够实现很高的压缩率,尤其是对于基于文本的数据来说。这样可以大大减少文件的大小以及所需的存储空间。

快速解压:LZW压缩算法通常比其他压缩算法更快,因此对于那些需要快速解压的应用程序来说,LZW是一个很好的选择。

普遍收养:LZW被广泛用于各种软件应用程序和操作系统之中,因此它是一种非常受欢迎的压缩和解压缩工具。

动态压缩:LZW采用了一种动态压缩算法,这意味着它能够根据被压缩的数据来进行调整。因此,即使对于具有重复模式的数据,它也能实现较高的压缩率。

缺点:

专利相关问题LZW压缩技术是在20世纪80年代获得专利的。多年来,由于需要使用相关许可协议来使用这项技术,因此它在某些应用场景中的应用受到了限制。

内存需求:LZW压缩算法需要大量的内存来存储压缩后的字典信息。对于那些内存资源有限的应用程序来说,这可能会成为一个问题。

压缩速度:LZW压缩算法在某些情况下可能会比其他压缩算法更慢,尤其是对于大型文件来说。这是因为LZW算法需要不断更新其字典数据。

适用范围有限:LZW压缩方式非常适合处理基于文本的数据,但对于其他类型的数据来说可能并不适用,比如图像或视频等数据,因为它们的压缩需求与文本数据不同。

资源:  

  • mit.edu
  • 戴夫·马歇尔
  • duke.edu
  • 迈克尔·迪珀斯坦
  • LZW(YouTube)
  • faculty.kfupm.edu.sa
              马上抢免费试听资格
意向课程:*必选
姓名:*必填
联系方式:*必填
QQ:
思博SPOTO在线咨询

相关资讯

即刻预约

免费试听-咨询课程-获取免费资料