对《数据结构、算法与应用:C++语言描述》中LZW算法的改进

在《数据结构、算法与应用:C++语言描述》((美)Sartaj Sahni著;汪诗林等译  北京:机械工业出版社,2000.1)第238页提到了用于文本压缩的LZW算法,该算法可以正确地处理文本文件,但对于二进制文件却经常会出现将文件压缩并解压后得到的文件与原文件不同的问题。

该书中将该算法用于文本压缩,而该算法又能正确处理文本文件,因而该算法在这个意义上说是正确的。

但压缩算法应该能处理各种格式的文件。下面,我就对书上的算法稍做修改使之能进行二进制文件的压缩。

 

1、问题分析

 

我对该算法进行黑盒测试,发现以下情况:

1)该算法能正确处理文本文件,且不论文件长短,不论英文还是汉字都能处理。

2)该算法对我测试的十几个二进制文件进行压缩并解压后文件都变短了。

3)怀疑是控制字符产生的影响,我在一个文本文件中了一些0x000xff等特殊字符,压缩并解压后出现问题。进行多次这样的试验,并将压缩并解压后的文件与原始文件进行比较,我发现特殊字符之前的内容均正确,而0x00之后的内容“面目全非”,其它特殊字符不会产生影响。而且,文件中所有0x00在压缩并解压后的文件中消失了,而其它字符均没有问题(原文件中0x00后的字符在解压后的文件中错位了)。推测是0x00的问题,我在文本文件中添入特殊字符但不添加0x00,此时结果正确。

据上面推断可知问题出现在该算法不能正确处理字符0x00

 

将某一文本文件第一个字符改为0x00,并用该文件作为测试数据对压缩程序进行调试。单步调试,当程序进入Compress函数,并执行到in.get(c)(原程序compress.cpp83行)时,由于第一个字符是0x00,因此c的值为0x00,到第84行,pcode的值变为0x00,到第87行,程序又读进一字符,c的值变为一个非0x00的值,不妨将该值设为C2,到第89unsigned long k = (pcode << ByteSize) + ck的值变为C2(因pcode等于0x00)。当运行到第91行“if (h.Search(k, e)) pcode = e.code”时,程序会忽略那个被移到k高位的0x00字符。因前256个字符在前面已经加入字典,h.Search(k, e)返回真(因为k=C2<256),pcode被赋值为C2,这实际上是把读进的前两个字符当一个字符(第二个字符)处理。这样就使0x00字符消失了。

 

1、问题解决

 

知道了问题的原因解决问题就不难了。一种方法是像数据链路层PPP协议把0x7e变换为0x7d,0x5e并把0x7d变换为0x7d,0x5d那样将0x00变换成两个其它字符,但这样实现起来比较麻烦。

 

下面介绍一种改进方法,只用添、改四五行代码即可实现。将key20位(最低位为第0位,低20位为有效信息)作为“多字符”标志,即若该标志位为1则表示该key所译出的字符数大于1,若该标志位为0则表示该key只能译出一个字符。显然,只有字典中低256个元素的key中“多字符”标志为0,以后添加的元素的key中“多字符”标志都为1。这样,如果一个key的高位是0x00字符在字典中的code,因其“多字符”标志为1,程序也会将它按多字符处理。修改的方法即在查字典和向字典中添加元素时都使用key的“多字符”标志。解压程序不用修改,修改后程序已调试通过,可处理各种二进制文件。

 

注:

 

原程序和修改后的程序下载:http://files.myopera.com/langchibi_zhou/files/lzw.rar

 

我修改的行后面有“//Modified by Zhou Xiaowei on Apr 13,2007,添加的行后面有“//Added by Zhou Xiaowei on Apr 13,2007

 

 

 

 

 

2007417

 
发布了24 篇原创文章 · 获赞 9 · 访问量 14万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章