python - 一般如何将递归程序转换为迭代程序?

标签 python recursion iteration

例如,将 BST 的预序遍历和中序遍历从递归转换为迭代是相对直接的。但后订单更难。

下面是原始的递归 BST 遍历函数:

Python 3

def traverse_rec(node):  # traversal of sub-tree at node.
    # pre-order work here:
    # print(node.val, end=' ')
    if node.lft:
        traverse_rec(node.lft)

    # in-order work here:
    print(node.val, end=' ')

    # post-order work here:
    # print(node.val, end=' ')
    if node.rt:
        traverse(node.rt),

我发现了一些递归函数的迭代版本(前序、中序、后序 BST 遍历),例如 here ,但我正在寻找 what the computer does with it's call stack 之后的迭代实现这样我就可以轻松地转换后序 BST 遍历,并且更一般地将递归代码转换为迭代代码。因此,每次调用函数时都应将“帧”推送到帧堆栈上,该“帧”记录函数返回时继续执行的位置,以及调用函数所需的任何可能被被调用函数更改的变量。函数返回时,帧会从帧堆栈中弹出。

最佳答案

这是我使用frame_stack的递归到迭代翻译:

def traverse_iter(node):
    # Iterative bst traversal. A (node, state) tuple is pushed onto frame_stack where a recursive call would occur.
    # state defines where to pick up the processing on return (on pop).
    # state: 0: Did not just return into this frame.
    #        1: Just returned from left child.
    #        2: Just returned from right child.
    # Only states 1 and 2 get pushed onto the frame_stack.
    # Generally, state would include any variables that are needed on return that get changed on the frame change
    # in addition to the program counter (pc).
    # Here, each node has all the data (val) needed, and state 1 or 2 acts as a pc to determine where to pick up
    # on return.
    frame_stack = []
    state = 0  # Didn't just return from a child(function call).
    while True:
        if node is None:    
            if frame_stack:  # Returning up recursion tree:
                node, state = frame_stack.pop()
            else:            # or completed traversal.
                break

        if state == 0:
            # Execute pre-order work here.
            #print(node.val, end=' ')
            if node.lft:  # Emmulate recursive call into left child.
                frame_stack.append((node, 1))
                node = node.lft
                continue

        if state == 0 or state == 1:
            # Execute in-order work here
            print(node.val, end=' ')

            if node.rt:
                frame_stack.append((node, 2))
                node = node.rt
                state = 0       # State to descend into child.
                continue

        # Returning from a right child or there was none:
        # Execute post-order work here.
        # print(node.val, end=' ')
        node = None     # finished with this node (and all below it).

一旦我“明白了”,我发现开发和理解上述内容相当简单,而且我使用的模式似乎通常可以扩展到任何递归到迭代翻译,因为它基于计算机的行为。我基本上将递归函数调用转换为变量的更新,这些变量被更改为新函数(此处的节点到子节点),并将它们的原始值与 pc(此处的状态)一起推送到帧堆栈(此处的节点);根据需要添加最少的支持逻辑。

我想知道是否有人可以提供一个示例,其中帧有效负载需要比(节点,状态)更多的内容才能从我们停止的函数返回中获取,或者简化我的 BST 遍历(同时保持其预、中、和后订单一般)。

关于python - 一般如何将递归程序转换为迭代程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59655419/

相关文章:

python - SelectField 返回值 wtf-forms

ios - 递归和 objective-c

Java继承与递归

algorithm - 递归求和二维数组的元素?

C# 大树迭代

javascript - 如何使用 Phantomjs 设置页面抓取之间的时间间隔

python - 如果下一行具有相同的第一个值,则删除行,python

python - 通过字符串进行二分查找

python - 在回调中反向转换 ctypes.py_object

python - 过滤 pytest 固定装置