知方号

知方号

Android 字符串压缩效率最高的方式

这篇文章主要是想要总结一下LZW的压缩/解压缩算法。因为写的时候花了好长好长的时间才想清楚应该怎么理解这个解压算法。。。

压缩过程(encode)

首先是压缩过程,伪代码如下:

初始化中间寄存器 A = 0for 每一个字符 K: 如果 AK 在 字典中: A = AK, 进入下一次循环 否则: **输出 A 的编码** **把 AK 加入字典** A = K

注意我们一开始要把字符集的所有单字符加入字典里面做初始化。

压缩的过程非常清晰易懂。但解码过程可能不那么好理解,因此我们在压缩过程中需要注意到1件事:

输出编码A的过程和把新的键值对加入字典是一起发生的

解码过程(decode)

LZW的解码所用的字典和编码所用的字典完全不一样,这也是LZW算法的一个优点所在:不需要存储字典表。注意解码时字典 key 和 value 的类型要互换一下,字典同样需要进行初始化。另外注意到一开始的第一个字符必然能直接解码。

伪代码如下:

// dict[A] = A 所代表的原始字符串解码第一个字符 K,输出K令 A = Kfor 每一个字符 K: 如果 K 在 字典中: 解码输出 K 把dict[A] + dict[K][0] 作为新的value放入字典 K不在字典中: dict[K] 必然是 dict[A] + dict[A][0] 把新的键值对加入字典 解码输出K 不论K在不在字典中,最后都有 A = K

解码过程和编码过程有一定的区别,最大的区别是当前要解的码可能不在字典中。这种情况我们可以这么解释:

K 不在字典中,说明K正是目前最后一个被加到字典中的项。那么我们最后一个加的项是什么呢?

根据编码过程中我们了解到的“输出编码A的过程和把新的键值对加入字典是一起发生的 ”

说明最后加的项正是上一个输出的编码 A 后面紧跟了一个字符。那么这个紧跟的字符是什么呢? 它A输出字符的首字符(因为K的前缀和A的前缀相同,而且这个字符正是A后面紧跟的多余的字符)

希望我写清楚了……

附代码:

def encode(bs): dic = {} for i in range(128): dic[(i,)] = i res = [] a = [] index = 128 for byte in bs: ak = a + [byte] if tuple(ak) in dic: a = ak else: res.append(dic[tuple(a)]) dic[tuple(ak)] = index index += 1 a = [byte] return resdef decode(bs): dic = {} index = 128 for i in range(index): dic[i] = [i] res= [dic[bs[0]][0]] a = bs[0] for byte in bs[1:]: if byte not in dic: new = dic[a] + [dic[a][0]] dic[byte] = new res += new else: res += dic[byte] newv = dic[a] + [dic[byte][0]] dic[len(dic)]= newv a = byte return res

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至lizi9903@foxmail.com举报,一经查实,本站将立刻删除。