如何将以下函数转换为尾递归函数?

时间:2015-04-21 02:08:40

标签: python algorithm recursion binary-tree tail-recursion

我跟着here跟着我正在尝试将正常的递归函数转换为尾递归函数。我设法理解斐波纳契和阶乘版本,但这个让我很难过。我理解算法在做什么,以及在转换中让我困惑的else语句。

在其他内部,它试图在放弃之前找到一个更接近您所寻找的数字,并且找到的数字小于您建议的数字。

我不确定如何编写使尾部递归的辅助函数。对于斐波那契和阶乘,我最终使用了累加器。是否有类似的东西可以在这里使用?

class BSTNode(object):
    """Binary search tree node."""

    def __init__(self, val, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

    def __repr__(self):
        return '(%s, %r, %r)' % (self.val, self.left, self.right)

def find_val_or_next_smallest(bst, x):
    """
    Get the greatest value <= x in a binary search tree.
    Returns None if no such value can be found.
    """
    if bst is None:
        return None
    elif bst.val == x:
        return x
    elif bst.val > x:
        return find_val_or_next_smallest(bst.left, x)
    else:
        right_best = find_val_or_next_smallest(bst.right, x)
        if right_best is None:
            return bst.val
        return right_best

我理解Python不支持尾递归优化以允许常量堆栈空间但我只是在Python中练习这样做,因为我喜欢语法

2 个答案:

答案 0 :(得分:3)

而不是做

if right_best is None:
    return bst.val

您可以将目前为止发现的最佳结果作为额外参数传递给递归调用,并使递归调用处理此检查。

def find_val_or_next_smallest(bst, x, best=None):
    """
    Get the greatest value <= x in a binary search tree.
    Returns None if no such value can be found.
    """
    if bst is None:
        return best
    elif bst.val == x:
        return x
    elif bst.val > x:
        return find_val_or_next_smallest(bst.left, x, best)
    else:
        # bst.val is guaranteed to be the best yet, since if we had
        # seen a better value higher up, the recursion would have gone
        # the other way from that node
        return find_val_or_next_smallest(bst.right, x, bst.val)

答案 1 :(得分:2)

要将函数转换为尾递归,您应该通过添加额外参数val来一直带着部分答案:

def find_val_or_next_smallest(bst, x, val=None):
    """
    Get the greatest value <= x in a binary search tree.
    Returns None if no such value can be found.
    """
    if bst is None:
        return val
    elif bst.val == x:
        val = x
    elif bst.val < x and (val is None or bst.val > val):
        val = bst.val

    if bst.val > x:
        return find_val_or_next_smallest(bst.left, x, val)
    else:
        return find_val_or_next_smallest(bst.right, x, val)

<强>更新

有一个尾递归意味着我们可以有一个迭代解决方案(相对于递归),并且可以通过将其转换为迭代解决方案轻松地在accepted answer上进行演示:

def find_val_or_next_smallest(bst, x, val=None):
    """
    Get the greatest value <= x in a binary search tree.
    Returns None if no such value can be found.
    """
    while True:
        if bst is None:
            return val
        elif bst.val == x:
            return x
        elif bst.val > x:
            bst = bst.left
        else:
            val = bst.val
            bst = bst.right