【问题标题】:Understanding Recursion in Tree Traversal [duplicate]了解树遍历中的递归
【发布时间】:2021-03-01 18:38:39
【问题描述】:

这个问题可能与this one 类似,但有细微差别。我想了解当有两个递归调用一个在另一个之下时,递归是如何工作的。

考虑以下对预排序的树遍历。

。 [参考:education.io]

我添加了一些打印语句来了解每个递归调用是如何工作的:

from Node import Node
from BinarySearchTree import BinarySearchTree


def preOrderPrint(node):
    if node is not None:
        print(node.val)
        preOrderPrint(node.leftChild)
        print('Done with left node')
        preOrderPrint(node.rightChild) 
        print('Done with right node')


BST = BinarySearchTree(6)
BST.insert(4)
BST.insert(9)
BST.insert(5)
BST.insert(2)
BST.insert(8)
BST.insert(12)

preOrderPrint(BST.root)

输出如下:

6
4
2
Done with left node
Done with right node
Done with left node
5
Done with left node
Done with right node
Done with right node
Done with left node
9
8
Done with left node
Done with right node
Done with left node
12
Done with left node
Done with right node
Done with right node
Done with right node

这是我的理解和问题:

因此,基本情况是当节点为 None 时递归终止。左边的递归首先发生并在节点沿着树向下时打印出节点。一旦它到达 2 的左节点,它就会终止。这显示在“Done with left node”的打印状态中。

权利的递归接管。最后访问的节点是 2,所以它从那里开始。它终止是因为 2 的右孩子是无。这显示在“Done with right node”的打印语句中。

现在,右递归上升到 4。问题:为什么代码在打印 5 之前打印“Done with left node”而不是再次打印 2?它如何知道左节点有完成了吗?你能解释一下递归使用的堆栈吗?或任何其他方式。

【问题讨论】:

  • 打印节点4的左节点(即节点2)已经完成,然后进入节点4的右节点(即节点5)。
  • 我会考虑if node.leftChild: print('Done with left child of', node.val) else: print('No left child of', node.val)。同上。
  • 递归调用框架等到它们的子调用完成后才恢复执行并最终返回。就堆栈而言,子调用被推送,最终弹出,然后父调用可以弹出。父级已经打印了 2 并且无法重新访问 - 每个帧内的执行都是从上到下正常的。我建议在您的打印件中添加缩进以帮助可视化,正如欺骗建议所表明的那样(您可以将树结构插入该可视化器)。将退化的树想象成一个链表,你会看到调用堆栈展开,然后所有的东西都一个接一个地弹出。
  • Here's 另一个可能有帮助的方法——它可能看起来不一样,但确实是——每帧两次调用,基本上遍历一棵完美的树。

标签: python recursion


【解决方案1】:

就像我的评论所暗示的那样,您不仅要为叶节点打印“完成...”;相反,您对树中的每个节点都这样做,甚至是中间节点。

为了更清楚地看到这一点,我建议更改您的功能:

def preOrderPrint(node):
    if node is not None:
        print(node.val)
        preOrderPrint(node.leftChild)
        print('Done with left node of node', node.val)
        preOrderPrint(node.rightChild) 
        print('Done with right node of node', node.val)

您的输出现在应该是:

6
4
2
Done with left node of node 2
Done with right node of node 2
Done with left node of node 4
5
...

【讨论】:

  • 递归如何知道它已经用节点 4 的左节点完成了?这让我很困惑。
  • @Rohit 因为子调用returns 控制给父并且父调用的print('Done with left node') 可以执行。
  • 因为您的程序指示在进入4 的左节点后立即打印"Done with left node of node 4"。因此,一旦程序从与4 的左节点相关的递归调用返回(不管有多少),它就会准确地打印出来。
  • 您的解释以及指向此的建议链接:stackoverflow.com/questions/63962871/… 非常有帮助!
猜你喜欢
  • 2014-12-21
  • 2016-08-24
  • 1970-01-01
  • 2022-11-21
  • 2018-07-12
  • 2014-03-11
  • 1970-01-01
  • 2017-05-11
  • 1970-01-01
相关资源
最近更新 更多