【问题标题】:Python finding paths of trees using recursionPython使用递归查找树的路径
【发布时间】:2017-09-24 02:23:04
【问题描述】:

我一直在尝试实现基于数字的 Huffman 编码算法。我已经完成了构建霍夫曼树的部分。但是递归算法没有按预期工作。它应该返回树中从根到指定节点的路径,但它总是返回错误的路径。

奇怪的是,代码似乎在做正确的事情,并且可以找到真正的路径。但它返回的结果总是不同的。

def get_encoding_for(symbol_p, node, encoding):
    global encoded_string
    result = encoding
    if not isinstance(node, list):
        if symbol_p == node:
            encoded_string = result
            return result
    else:
        for n in node:
            index = str(node.index(n))
            # print("Node {} with index {}".format(n, index))
            result = get_encoding_for(symbol_p, n, encoding + index)

    return result

这棵树是用简单的列表来构造的。

The huffman tree looks like: [[3.0, [1.0, 2.0]], [4.0, 5.0]]

这是使用元素 1、2、3、4、5 的简单树的示例输出。

Loop 1.0. Node 1.0 -> Coding 010:
Loop 2.0. Node 2.0 -> Coding 011:
Loop 3.0. Node 3.0 -> Coding 00:
Loop 4.0. Node 4.0 -> Coding 10:
Loop 5.0. Node 5.0 -> Coding 11:

这是我希望函数返回的内容,但在所有五次迭代中它只返回“11”。我不得不使用一个全局变量来“拦截”正确的编码,我对此并不满意......我认为问题在于返回。我尝试了很多返回的方法,但都没有奏效。

有人能告诉我递归有什么问题吗?非常感谢!

【问题讨论】:

  • 问题是当它找到正确的路径时你的递归并没有结束,它只是继续下去,直到它遍历树中的每一条路径。这就是为什么返回值总是11 - 这是你树中的最终路径。您需要添加一种机制来检测您是否找到了要搜索的元素,并停止for n in node: 循环。
  • 谢谢您的回复,但是为什么“返回结果”不会停止该方法?
  • 您的for 循环中没有returnreturn 发生在 循环之后,因此您得到的是 last 值,而不是正确的值。
  • 如果for循环中有return,它会过早停止并且无法找到路径...每个节点可以有尽可能多的子节点。
  • 这就是为什么我说你需要一种机制来让你在正确的时间停下来......

标签: python recursion tree return path-finding


【解决方案1】:

另一种方法(与我的第一个答案中的方法不同)是将生成路径与停止逻辑分开。

def paths(bintree):
    if isinstance(bintree, list):
        for i, p in ((0,'0'), (1,'1')):
            for val, path in paths(bintree[i]):
                yield (val, p + path)
    else:
        yield (bintree, '')

def encoding2(i, bintree):
    for val, path in paths(hufftree):
        if i == val:
            return path
    return ''

# Test
hufftree = [[3, [1, 2]], [4, 5]]
for v in paths(hufftree): print(v)
for i in range(6):
    print(encoding2(i, hufftree))
# Prints

010
011
00
10
11

此时,可能会考虑创建一个将值映射到编码的字典。

huffdict = dict(paths(hufftree))
for i in range(6):
    print(huffdict.get(i, ''))
# Prints same as above

【讨论】:

    【解决方案2】:

    在树中搜索一个项目有点棘手。递归完成,返回需要信号成功(再次返回)或失败(再次递归)。迭代完成,返回很容易,但需要一个可能的搜索位置的显式堆栈。以下是前者,利用树的二元结构。注 1:我使用的名称使 me 更容易正确书写。它们不一定“更好”。注 2:我在测试中添加了一个“未找到”案例。

    def encoding(char, bintree, path):
        if isinstance(bintree, list):
            p = encoding(char, bintree[0], path+'0')
            if p:
                return p
            return encoding(char, bintree[1], path+'1')
        else:
            return path if char == bintree else ''
    
    # Test
    hufftree = [[3, [1, 2]], [4, 5]]
    for i in range(6):
        print(encoding(i, hufftree, ''))
    # Prints
    
    010
    011
    00
    10
    11
    

    【讨论】:

    • 感谢您的回复!是的,解决方案很有意义。我想知道如何将它扩展到三元、四元树?循环和返回正在杀死我......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-14
    • 1970-01-01
    • 2013-03-14
    • 1970-01-01
    • 1970-01-01
    • 2011-04-22
    • 1970-01-01
    相关资源
    最近更新 更多