LZW算法的个人理解与简单Python实现

来源:互联网 发布:配电网设计超人软件 编辑:程序博客网 时间:2024/05/16 05:22

参考http://bcb.lcsoft.net/document-2027.html

我是参照他括号里给出不同的实现,即“STRING  =  STRING  + CHARACTER" 和 “CHARACTER  =  first  character  in  STRING "

参考博文对LZW算法的解释比较详细。所以这里我只谈谈我个人是如何理解这个算法。表达不是很清晰,请原谅。

压缩过程不难理解。我主要说说解压过程。
无论是压缩还是解压,都是围绕字典展开的。所以要理解LZW算法,应该首先明白字典创建以及还原的原理。
所以,如何理解算法中的这句话“add  OLD_CODE  +  CHARACTER  to  the  translation  table ”是关键。我的理解是OLD_CODE是上一个数字代码对应的字符串(对应程序中变量oldCodeStr),CHARACTER是当前数字代码对应字符串的首个字符(对应程序中curCodeStr[0])。

我们知道,每个代码数字(设为x)被输出都是有原因的。原因就是遇到了字典中没有的字符串(设为字符串a)。为了可以还原字典,我们要得到a。而由压缩的原理可知,a = (x在字典中对应的字符串(设为b)) + (原字符流中b后面紧接着的字符(设为c))(对应语句3)。(因为在压缩时,遇到字典中没有的字符串时,是将这个字符串的前缀的代码数字输出的,反过来,代码数字对应的字符串也只是所遇到的字典中没有的字符串的前缀)。其中c也就是下一个数字代码所对应字符串的首个字符。


也就是说,每一个数字都代表着压缩时字典多了一个条目。而这个条目具体是什么,必须等到输入下一个数字才能得到(因为,下一个数字代码对应的字符串的首字符就是导致上个数字代码输出的那个字典中没有的字符串的最后一个字符)。所以,在解压时,第一个数字代码没有还原字典条目,之后每个数字代码都还原出一个字典条目。


分支2是当前数字在字典中还没有对应的字符串的情况。这时,可以断定这个数字对应的字符串就是此次要还原的字典条目。(因为,当前数字被输出,则它肯定已经在压缩字典中了,而压缩字典中还没有被还原的只有此次要被还原的字典条目了。)而此次要还原的字典条目前缀的已知是b,所以当前数字对应的字符串为b + (b的首个字符)(对应语句2)。

python简单示例,程序假设待压缩的字符串只含a、b、c三种字符

import sysdef compress():    inputStr = raw_input('Please input string that needs to be encoded : ')    hints = ['prefix', 'curChar', 'curStr', 'isCurStrInDict', 'addedDictItem', 'output']    print hints[0].ljust(20), hints[1].ljust(20), hints[2].ljust(20), hints[3].ljust(20)\    , hints[4].ljust(20), hints[5].ljust(20)    prefix = curChar = curStr = output = ans = ''    isCurStrInDict = False    dict = {'a':1, 'b':2, 'c':3}        for curChar in inputStr:        curStr = prefix + curChar        print prefix.ljust(20), curChar.ljust(20), curStr.ljust(20),        if curStr in dict:            output = ''            isCurStrInDict = True            prefix = curStr        else:            output = str(dict[prefix])            isCurStrInDict = False            prefix = curChar            dict[curStr] = len(dict) + 1                print str(isCurStrInDict).ljust(20),                    if isCurStrInDict:            print ''        else:            print str(curStr+':'+str(dict[curStr])).ljust(20), output.ljust(20)                if output != '':            ans = ans + ' ' + output            output = str(dict[prefix])            print prefix.ljust(20), 'empty'.ljust(20), prefix.ljust(20), 'True'.ljust(20)\    , ''.ljust(20), output.ljust(20)    ans = ans + ' ' + output    print ansdef decompress():    inputStr = raw_input('Please input code that needs to be decoded : ')    inputStrArray = inputStr.split()    inputIntArray = [int(i) for i in inputStrArray]        hints = ['curCode', 'oldCodeStr', 'isCurCodeInDict', 'curCodeStr', 'addedDictItem']    print hints[0].ljust(20), hints[1].ljust(20), hints[2].ljust(20), hints[3].ljust(20)\    , hints[4].ljust(20)    ans = curCodeStr = oldCodeStr = ''    dicSize = 3    isCurCodeInDict = True    dict = {1:'a', 2:'b', 3:'c'}        for curCode in inputIntArray:        if curCode  in dict:            curCodeStr = dict[curCode]            isCurCodeInDict = True        else:            #2            curCodeStr = oldCodeStr + oldCodeStr[0]            isCurCodeInDict = False                    if oldCodeStr != '':            dicSize = dicSize + 1            dict[dicSize] = oldCodeStr + curCodeStr[0]                print str(curCode).ljust(20), oldCodeStr.ljust(20), str(isCurCodeInDict).ljust(20)\        , curCodeStr.ljust(20), str(dicSize) + ':' + dict[dicSize]                oldCodeStr = curCodeStr        ans = ans + curCodeStr            print ansif __name__ == "__main__":    compress()    decompress()    


0 0