LZW压缩算法——简明原理与实现

来源:互联网 发布:8051单片机引脚图 编辑:程序博客网 时间:2024/05/21 15:07

LZW和哈夫曼编码一样,是无损压缩中的一种。该算法通过建立字典,实现字符重用与编码,适用于source中重复率很高的文本压缩。本文首先讲下LZW的编解码原理,然后给出LZW的实现code。


*********************原理*********************

编码:

  • 编码0-255用来存储Ascii码为[0,255]的字符,放在字典里。
  • 编码从256开始,将出现过的字符计入字典
  • 核心思想:利用字符的可重用性,每当往结果输出一个编码,就将一个新的string存入dictionary

算法流程:


举例:






解码:

编码的逆过程,若编码是string到int的映射,我们可以将解码过程描述为int到string的映射。

  • LZW算法的解码无需在编码过程中存储字典(这样太浪费空间了)
  • 解码初始化依旧用256个Ascii码,后面每读入一个编码(int),检查其在dictionary中的映射,并不断将新的映射加入字典

算法流程:


解码的例子建议读者用下面的代码直接调试吧~



*********************实现*********************


我用C++实现的,Compress和Decompress两个函数分别实现编解码

[cpp] view plain copy
  1. /************************************************************************/  
  2. /*  File Name: LZW.cpp 
  3. *       @Function: Lossless Compression 
  4.         @Author: Sophia Zhang  
  5.         @Create Time: 2012-9-19 10:00 
  6.         @Last Modify: 2012-9-19 11:10 
  7. */  
  8. /************************************************************************/  
  9.   
  10. #include"iostream"  
  11. #include "map"  
  12. #include "string"  
  13. #include "iterator"  
  14. #include "vector"  
  15. using namespace std;  
  16.   
  17. /************************************************************************/  
  18. /*  Compress Module 
  19. *       input:  
  20.             str - the string need to be compressed 
  21.             result - compress result 
  22. */  
  23. /************************************************************************/  
  24. template<typename TypeIterator>  
  25. TypeIterator Compress(string str, TypeIterator result)  
  26. {  
  27.     //Build the dictionary  
  28.     map<string,int>dictionary;  
  29.     int Dictsize=256;  
  30.     for(int i=0;i<Dictsize;i++)  
  31.         dictionary[string(1,i)]=i;  
  32.   
  33.     char z;  
  34.     string S;  
  35.   
  36.     for(string::const_iterator it = str.begin(); it!=str.end(); it++)  
  37.     {  
  38.          z = *it;  
  39.           
  40.          if(dictionary.count(S+z))//can find S  
  41.              S+=z;  
  42.          else//S is not in dictionary D  
  43.          {  
  44.              *result++ = dictionary[S]; //output pointer (S,D)  
  45.              dictionary[S+z] = Dictsize++; //add to dictionary  
  46.              S = z;  
  47.          }  
  48.     }  
  49.     if(!S.empty())  
  50.         *result++ = dictionary[S];  
  51.     return result;  
  52. }  
  53.   
  54. /************************************************************************/  
  55. /*  Decompress Module 
  56. *       input:  
  57.             TypeIterator result - compression result, to be decompressed 
  58. */  
  59. /************************************************************************/  
  60. template<typename TypeIterator>  
  61. string Decompress(TypeIterator result)  
  62. {  
  63.     map<int,string>inv_dictionary;  
  64.     int Dictsize=256;  
  65.     for(int i=0;i<Dictsize;i++)  
  66.         inv_dictionary[i] = string(1,i);  
  67.   
  68.     char z;  
  69.     string S;  
  70.     string entry;  
  71.     string res;  
  72.     Dictsize--;//because the first "Dictsize++" make no sense, it has only one char in [0,255]  
  73.   
  74.     for(TypeIterator::iterator it = result.begin(); it!=result.end(); it++)  
  75.     {  
  76.         int k = *it;  
  77.         if(inv_dictionary.count(k))  
  78.             entry = inv_dictionary[k];  
  79.         else if(k==Dictsize)  
  80.             entry = S+ S[0];  
  81.         else  
  82.             throw "Bad compression code";  
  83.   
  84.         res += entry;  
  85.           
  86.         inv_dictionary[Dictsize++] = S + entry[0];  
  87.         S = entry;  
  88.     }  
  89.     return res;  
  90. }  
  91.   
  92.   
  93. int main()  
  94. {  
  95.     typedef vector<int> TypeIterator;  
  96.     TypeIterator compress_res;  
  97.     string S = "the/rain/in/Spain/falls/mainly/on/the/plain";  
  98.     Compress(S,std::back_inserter(compress_res));  
  99. //  copy(compress_res.begin(),compress_res.end(),std::ostream_iterator<int>(std::cout,","));  
  100. //  std::cout<<std::endl;  
  101.   
  102.     //output the compressed result  
  103.     for( TypeIterator::iterator it= compress_res.begin(); it!=compress_res.end(); it++)  
  104.         cout<<(*it)<<endl;  
  105.   
  106.     //decompress the compressed result  
  107.     string decompress = Decompress(compress_res);  
  108.     cout<<decompress<<endl;  
  109. }  

result:



Reference:

1. http://www.stringology.org/DataCompression/lzw-e/index_en.html

2. http://www.dspguide.com/ch27/5.htm

3. http://marknelson.us/1989/10/01/lzw-data-compression/

4. http://www.ccs.neu.edu/home/jnl22/oldsite/cshonor/jeff.html

0 0
原创粉丝点击