【问题标题】:Python tree traversal recursion depth exceeded超出Python树遍历递归深度
【发布时间】:2011-10-10 01:54:09
【问题描述】:

我有一个段树,其中包含一系列数字的数据(选择的数据结构here)。代码如下:

class SegmentTree:
    def __init__(self, N):
        def _init(b, e):
            if b is e:
                data = foo() # No dependency
                return Node(b, e, data, None, None)
            else:
                mid = (b + e ) / 2

                L = _init(b, mid)
                R = _init(mid + 1, e)

                data = foo() #Data depends on L and R

                return Node(b, e, data, L, R)

        self.root = _init(1, N)

这在 N 大约 300 时失败,并且出现最大递归深度超出错误。有没有办法迭代而不是递归地创建树?

【问题讨论】:

    标签: python algorithm optimization tree


    【解决方案1】:

    真正的问题不是算法的递归深度,对于像 300 这样的值,递归深度应该是 10 左右,而是您将数字与 is 进行比较。 is 关键字检查对象身份,而 == 检查相等性:

    >>> 300 == 299+1
    True
    >>> 300 is 299+1
    False
    

    因为应该终止递归的 if 条件永远不会为真,并且函数将继续递归,即使 be 相等。

    如果您更改if,这个问题应该会消失:

    if b == e:
       ...
    

    对于小数字,问题可能不会发生,因为 Python "caches" and reuses the objects 用于整数到一定大小。

    【讨论】:

      【解决方案2】:

      一般而言,从递归转换为迭代的方式是手动维护堆栈(或队列)。

      类似:

       while stack is not empty:
           item = pop from stack
      
           do processing (such as adding onto the node)
      
           push L and R onto the stack
      

      堆栈确实在内存中增长,因为对于您弹出的每个项目,您都在推送两个。

      【讨论】:

      • 是的,我想这样做,但我需要在(递归地)创建 L 和 R 节点之后对当前节点进行处理。我不确定将当前节点存放在哪里/如何存放以供将来处理 - 在单独的堆栈上?
      • 嗯,通常有更好的方法来实现树遍历(尽管它们可能会因指针旋转和其他东西而变得复杂)而不是使用“堆栈”。毕竟,如果你在堆上使用堆栈,你并没有真正节省多少空间(除了一个常数因素,因为你需要保存更少的状态)
      猜你喜欢
      • 1970-01-01
      • 2013-04-06
      • 2012-11-20
      • 2011-12-31
      • 1970-01-01
      • 2018-07-12
      • 2014-03-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多