将递归转换为尾递归

时间:2017-11-07 15:33:32

标签: python algorithm recursion

我正在阅读将递归算法转换为迭代算法。我遇到了一篇博客文章http://blog.moertel.com/posts/2013-05-11-recursive-to-iterative.html,解释了将递归算法首先转换为尾递归算法然后将尾递归转换为迭代算法的过程。在帖子中,我们解释说当我们想要将递归算法转换为尾递归算法时,我们首先要了解return of the recursive callreturn statement of the calling function.之间发生了什么,一旦完成,我们应该尝试将一个秘密功能/累加器参数添加到递归函数,然后决定返回什么。我已经按照博客文章中给出的示例的概念进行了操作,但我无法解决博客末尾的练习。我无法确定我的累加器参数应该是什么?我应该如何根据累加器参数做出决定。我不想要一个解决方案,但有一些关于如何解决这个问题的指示。这是练习代码:

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 

提前致谢!

1 个答案:

答案 0 :(得分:1)

我发布此内容以替换昨天的评论并显示代码。

在递归算法中,每次调用都会创建一个包含函数局部变量和传递参数的堆栈帧。所有堆栈帧一起保存某种状态信息。当您要避免递归时,将不会有额外的堆栈帧。因此,必须在非递归函数中维护数据的重要部分。

现在到代码。我试图严格按照说明进行操作。

这是原始来源。我刚刚省略了docstring,并在elif之后立即将return替换为if s(只是首选样式的问题)。

def find_val_or_next_smallest1(bst, x):
    if bst is None:
        return None
    if bst.val == x:
        return x
    if bst.val > x:
        return find_val_or_next_smallest1(bst.left, x)
    else:
        right_best = find_val_or_next_smallest1(bst.right, x)
        if right_best is None:
            return bst.val
        return right_best

现在到尾递归。有四个分支。两个非递归,一个已经尾递归,第四个需要重写:

    right_best = find_val_or_next_smallest1(bst.right, x)
    if right_best is None:
        return bst.val
    return right_best

此分支选择bst.val或调用结果,以较好者为准。呼叫必须最后完成,因此bst.val必须简单地传递给它。该函数获取一个新参数,其含义是“如果找不到更好的东西,则返回此项”。在更改之前,如果您没有找到任何内容,则返回“无”。所以我们只需要替换None值。我调用了新参数found,因为它是我们迄今为止所发现的。

def find_val_or_next_smallest2(bst, x, found=None):
    if bst is None:
        return found
    if bst.val == x:
        return x
    if bst.val > x:
        return find_val_or_next_smallest2(bst.left, x, found)
    else:
        return find_val_or_next_smallest2(bst.right, x, found=bst.val)

直接转换,如博客:

def find_val_or_next_smallest3(bst, x, found=None):
    while True:
        if bst is None:
            return found
        if bst.val == x:
            return x
        if bst.val > x:
            bst, x, found =  bst.left, x, found
        else:
            bst, x, found =  bst.right, x, bst.val

和清理:

def find_val_or_next_smallest4(bst, x):
    found=None
    while True:
        if bst is None:
            return found
        if bst.val == x:
            return x
        if bst.val > x:
            bst = bst.left
        else:
            bst, found = bst.right, bst.val