【发布时间】:2021-03-01 18:38:39
【问题描述】:
这个问题可能与this one 类似,但有细微差别。我想了解当有两个递归调用一个在另一个之下时,递归是如何工作的。
考虑以下对预排序的树遍历。
我添加了一些打印语句来了解每个递归调用是如何工作的:
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 另一个可能有帮助的方法——它可能看起来不一样,但确实是——每帧两次调用,基本上遍历一棵完美的树。