LZW编解码算法原理及分析


数据压缩实验(三)

一、LZW概述

  • 第二类词典编码——LZW

LZW属于第二类词典编码,其基本思想是:企图从输入的数据中创建一个“短语词典”,这种短语词典可以是任意字符的组合。编码数据过程中,当遇到已经在字典中出现的“短语”时,编码器就输出这个词典中的短语的“索引号”,而不是短语本身。

J.Ziv和A.Lempel在1978年首次发表了介绍第二类词典编码算法的文章。在他们的研究基础上,Terry A.Welch在1984年发表了改进这种编码算法的文章,因此把这种编码方法称为LZW(Lempel-Ziv Walch)压缩编码。

二、LZW编解码原理

1.LZW编码

(1)算法原理

代号代替短语:LZW的编码思想是不断地从字符流中提取新的字符串,通俗地理解为新“词条”,然后用“代号”也就是码字表示这个“词条”。这样一来,对字符流的编码就变成了用码字(code word)去替换字符(String),生成码字流且只输出码字流,从而达到压缩数据的目的。

动态生成词典,新词条等于旧词条加新字符:LZW编码需要从输入的数据中创建短语词典,LZW编码器通过管理这个词典完成输入(短语)与输出(短语的索引号)之间的转换。

词典在开始时初始化不能为空,必须包含字符流中所有单个字符,即在编码匹配时至少能找到长度为1的匹配串。

输入字符输出码字:LZW编码器的输入是字符流,字符流可以是用8位ASCII字符组成的字符串,而输出是用n位(例如12位)表示的码字流。

(2)算法流程

步骤1:将词典初始化为包含所有可能的单字符,当前前缀P初始化为空。

步骤2:当前字符 C = 字符流中的下一个字符。

步骤3:判断 P+C 是否在词典中:

     1. 如果“是”,则用 C 扩展 P ,即令 P = P+C,返回步骤2。

     2.如果“否”,则
        (1) 输出与当前前缀 P 相对应的码字 W ;
        (2) 将 P+C 添加到词典中;
        (3) 令 P = C,并返回到步骤2。

具体如下图所示:

请添加图片描述

2.LZW解码

(1)算法原理

LZW解码算法开始时,译码词典和编码词典相同,包含所有可能的前缀根;

边解码边生成新词条,新词条等于旧词条加新字符。

(2)算法流程

步骤 1 :在开始译码时词典包含所有可能的前缀根。

步骤 2 :令 CW = 码字流中的第一个码字

步骤 3 :输出当前字符串 CW 到码字流。

步骤 4 :先前码字 PW = 当前码字 CW 。

步骤 5 :当前码字 CW = 码字流的下一个码字。

步骤 6 :判断当前字符串 CW是否在词典中:

     1. 如果 ” 是 ” ,则

         (1) 把当前字符串 CW 输出到字符流;
         (2) 当前前缀 P = 先前字符串 PW ;
         (3) 当前字符 C = 当前字符串 CW 的第一个字符;
         (4) 把字符串 P+C 添加到词典;
         (5) PW = CW 。

     2. 如果 ” 否 ” ,则

         (1)当前前缀 P = 先前字符串 PW ;
         (2) 当前字符 C = 当前字符串 CW 的第一个字符;
         (3) 输出字符串 P+C 到字符流 , 然后把它添加到词典中;
         (4) PW = CW 。

步骤7:判断码字流中是否还有码字要译:

     1. 如果 ” 是 ” ,就返回步骤4。
     2. 如果 ” 否 ”,则结束。

具体如下伪代码所示:

请添加图片描述

3.实验过程

(1)数据结构分析

尾缀字符(suffix)
母节点(parent)
第一个孩子节点( firstchild )
下一个兄弟节点(nextsibling)

树用数组dict[ ]表示,数组下标用pointer表示,所以dict[pointer]表示一个节点

  dict[pointer].suffix
  dict[pointer].parent
  dict[pointer].firstchild
  dict[pointer].nextsibling

(2)主函数


int main( int argc, char **argv){
   
	FILE *fp;
	BITFILE *bf;
	if( 4 > argc){
   
		fprintf( stdout, "usage: \n%s <o> <ifile> <ofile>\n", argv[0]);
		fprintf( stdout, "\t<o>: E or D reffers encode or decode\n");
		fprintf( stdout, "\t<ifile>: input file name\n");
		fprintf( stdout, "\t<ofile>: output file name\n");
		return -1;
	}
	if( 'E' == argv[1][0]){
    // do encoding
		fp = fopen( argv[2], "rb");
		bf = OpenBitFileOutput( argv[3]);
		if( NULL!=fp && NULL!=bf){
   
			LZWEncode( fp, bf);
			fclose( fp);
			CloseBitFileOutput( bf);
			fprintf( stdout, "encoding done\n&#
  • 0
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值