Python,将迭代函数转换为递归函数

时间:2018-09-25 12:37:12

标签: python loops recursion

我创建了一个迭代函数,该函数输出4 3 2 1 0 1 2 3 4。

def bounce2(n):
    s = n
    for i in range(n):
        print(n)
        n = n-1

    if n <= 0:
        for i in range(s+1):
            print(-n)
            n = n-1
    return
bounce2(4)

如果我想要一个功能完全相同的递归函数,我应该怎么想?

4 个答案:

答案 0 :(得分:11)

尝试一下:

def bounce(n):
    if n >= 0:
        print(n)
        bounce(n - 1)

        if n:
            print(n)

bounce(4)

输出将是: 4 3 2 1个 0 1个 2 3 4

答案 1 :(得分:2)

预期输出:

4 3 2 1 0 1 2 3 4

让我把它放在图表中:

4
  3
    2
      1
        0
      1
    2
  3
4

我们将其放入代码中

def bounce(n):
    print(n)
    if n:
        bounce(n - 1)
        print(n)

或者我可以将它视为遍历树-上下(在这种情况下,树是线性的):

↓
  4
↓ | ↑
  3
↓ | ↑
  2
↓ | ↑
  1
↓ | ↑
  0

如何执行tree traversal有多种方法,我将在这里选择DFS-depth-first search

DFS伪代码:

procedure DFS(G,v):
    label v as discovered
    for all edges from v to w in G.adjacentEdges(v) do
        if vertex w is not labeled as discovered then
            recursively call DFS(G,w)

实际上,它是为图形设计的,而不仅仅是树木。对于树木,我们不必做“被发现的标签”部分。

将此DFS转换为Python:

def dfs(node):
    for child_node in node:
        dfs(child_node)

4 3 2 1 0情况下,我们不需要for,因为只有一个或零个子节点-n - 1,只要n > 0

def our_dfs(n):
    if n > 0:
        child_node = n - 1
        our_dfs(child_node)

但这只是遍历,还没有真正有用的方法。让我们注入我们的“业务逻辑”:

def bounce(n):
    # stuff that happens before we go down
    print(n)
    # descend
    if n > 0:
        child_node = n - 1
        bounce(child_node)
    # stuff that happens after we are back from processing the subtree
    if n > 0:
        print(n)

因为我们相信良好的工艺水平,并且希望产生清晰的代码(好吧,我现在开始在开玩笑),所以我们希望只做一件事的函数-DFS的一个函数,一个代表我们的树的函数,一个单独的函数( s)了解我们的业务逻辑:

def dfs(node, child_factory, before_stuff, after_stuff):
    before_stuff(node)
    for child_node in get_child_nodes(node):
        dfs(child_node, child_factory, before_stuff, after_stuff)
    after_stuff(node)

def get_child_nodes(n):
    if n:
        yield n - 1

def print_before(node):
    print(node)

def print_after(node):
    if node:
        print(node)

def bounce(n):
    dfs(n, get_child_nodes, print_before, print_after)

bounce(4)

也许我们可以通过使用嵌套函数来简化dfs函数:

def dfs(node, child_factory, before_stuff, after_stuff):
    def f(node):
        before_stuff(node)
        for child_node in get_child_nodes(node):
            f(child_node)
        after_stuff(node)
    f(node)

嘿,看一下,我还有一个主意...我们可以将其修改为一个返回可以执行DFS的函数(closure)的函数:

def make_dfs(child_factory, before_stuff, after_stuff):
    def dfs(node):
        before_stuff(node)
        for child_node in get_child_nodes(node):
            dfs(child_node)
        after_stuff(node)
    return dfs

所以跳出程序现在变为:

def get_child_nodes(n):
    if n:
        yield n - 1

def print_before(node):
    print(node)

def print_after(node):
    if node:
        print(node)

def make_dfs(child_factory, before_stuff, after_stuff):
    def dfs(node):
        before_stuff(node)
        for child_node in get_child_nodes(node):
            dfs(child_node)
        after_stuff(node)
    return dfs

bounce = make_dfs(get_child_nodes, print_before, print_after)

bounce(4)

那么,这个解决方案有什么优点呢? (请注意:部分还是在开玩笑)您知道,Python有一个recursion limit。可以嵌套多少个函数调用的数量是有限的,并且这个数量非常低。使用递归函数处理未知输入是一个很大的缺点(有时甚至是安全问题)。所以现在怎么办?好吧,只需将make_dfs的实现替换为基于堆栈的内容(请参见DFS Wikipedia页面),而不要使用递归。做完了您无需触摸其他任何东西。

答案 2 :(得分:1)

@ mehrdad-pedramfar发布了一个很好的答案。您也可以尝试更详细的方法:

def my_recursion(current_value, first_portion):
    if current_value == 5:
        return
    print(current_value)
    if current_value == 0 or not first_portion:
        my_recursion(current_value + 1, False)

    elif first_portion:
        my_recursion(current_value - 1, True)


my_recursion(4, True)

答案 3 :(得分:-1)

与第一个基本相同。输出是不同的-您将得到双0。 只是为了显示您可以在递归调用之前和之后进行打印。

def bounce(n):

    if n >= 0:
        print(n)
        bounce(n - 1)
        print(n)

3 2 1个 0 0 1个 2 3