我正在研究将霍夫曼树存储在文件中的有效方法,以允许解码器重建霍夫曼树并正确解码文件。目前我已经创建了一个函数来创建给定频率的霍夫曼编码。
我看到Efficient way of storing Huffman tree,所以我写了一个递归函数来模仿帖子答案中的递归函数:
>>> huffman = [(b'A', '00'), (b'C', '01'), (b'E', '10'), (b'B', '110'), (b'D', '111')]
>>> write(hf)
b'001A1C01E01B1D'
在帖子中,答案使用对象来包含节点叶子。但是,我想将字符串直接解码为上面的huffman
变量中的元组列表。我尝试了这个,并提出了以下功能,这有点有用:
def read(p):
if p[0] == "1":
x = p[1]
p = p[2:]
if len(p) == 0:
c = [(x, "")]
else:
b = read(p)
for a in range(len(b)):
b[a] = (b[a][0], "1" + b[a][1])
c = [(x, "0")] + b
return c
if p[0] == "0":
c = read(p[1:])
return c
该函数在调用时返回:
>>> read("001C1A01E01D1B")
[('C', '0'), ('A', '10'), ('E', '110'), ('D', '1110'), ('B', '1111')]
这显然与上面的原始字典huffman
不同。
如何在不使用节点类的情况下递归解码霍夫曼树词典,并获取原始词典?
答案 0 :(得分:0)
首先,您传递给read()
函数'001C1A01E01D1B'
的字符串与您在上面的说明中显示的字符串不同,并且不是引用页面{{1}中使用的字符串}。解决此问题,您的代码会产生更好的输出,尽管仍然不正确:
'001A1C01E01B1D'
就解码而言,让递归为我们完成工作:
[('A', '0'), ('C', '10'), ('E', '110'), ('B', '1110'), ('D', '1111')]
该例程的递归版本将未解析的字符串剩余部分返回作为第二个结果。前端函数将其删除,并返回所需结果:
class HuffmanSyntaxError(Exception):
''' Raised due to incorrect or extra encoded string elements '''
def read_recursive(string, code=''):
if string[0] == "0":
first, string = read_recursive(string[1:], code + "0")
second, string = read_recursive(string, code + "1")
return [*first, *second], string
if string[0] == "1":
return [(string[1], code)], string[2:]
raise HuffmanSyntaxError(string) # unknown option
def read(string):
array, string = read_recursive(string)
if string: # left over input
raise HuffmanSyntaxError(string)
return array
print(read("001A1C01E01B1D"))