从字符串解码霍夫曼树

时间:2017-03-25 18:22:21

标签: python string dictionary recursion huffman-code

我正在研究将霍夫曼树存储在文件中的有效方法,以允许解码器重建霍夫曼树并正确解码文件。目前我已经创建了一个函数来创建给定频率的霍夫曼编码。

我看到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不同。

如何在不使用节点类的情况下递归解码霍夫曼树词典,并获取原始词典?

1 个答案:

答案 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"))