我目前正在研究二叉树。我遇到了这个非常高效的遍历树的代码(在本例中,这是一个按顺序遍历)。它使用递归,这是我理解的一个概念。然而,我似乎无法理解这到底是如何工作的。最让我困惑的是,它是如何在每次列表中上升的,这样才能开始。左并不总是相同的数字。请有人一步一步地告诉我这是如何沿树向上移动的。提前谢谢
编辑以增加问题的清晰度:
我的困惑之处在于,我似乎找不到代码的位置,“知道”它被遍历到4,现在下一个返回的元素是2。机制在哪里,现在停在2并返回它,等等?
class Node():
def __init__(self, data):
self.data = data
self.left = None
self.right = None
def __str__(self):
return str(self.data)
class BinaryTree(object):
def __init__(self, root):
self.root = Node(root)
def inorder_print(self, start, traversal):
"""Left -> root -> right"""
if start:
traversal = self.inorder_print(start.left, traversal)
traversal += (str(start.data) + "-")
traversal = self.inorder_print(start.right, traversal)
return traversal
tree = BinaryTree(1)
tree.root.left = Node(2)
tree.root.right = Node(3)
tree.root.left.left = Node(4)
tree.root.left.right = Node(5)
tree.root.right.left = Node(6)
tree.root.right.right = Node(7)
tree.root.right.right.right = Node(8)
print(tree.inorder_print(tree.root, ""))
好吧,再坐一会儿,想清楚了。思想我张贴我的思想,这样这个问题就可以标记为已回答。
理解算法路径的一个有用工具是向其添加日志记录。
def inorder_print(self, start, traversal, indent=""):
"""Left -> root -> right"""
if start:
print(f"{indent} {start.data} <- '{traversal}'")
traversal = self.inorder_print(start.left, traversal, indent+" ")
traversal += (str(start.data) + "-")
print(f"{indent} {start.data} -- '{traversal}'")
traversal = self.inorder_print(start.right, traversal, indent+" ")
print(f"{indent} {start.data} -> '{traversal}'")
return traversal
允许我们可视化树以及每个节点添加到遍历中的顺序:
1 <- ''
2 <- ''
4 <- ''
4 -- '4-'
4 -> '4-'
2 -- '4-2-'
5 <- '4-2-'
5 -- '4-2-5-'
5 -> '4-2-5-'
2 -> '4-2-5-'
1 -- '4-2-5-1-'
3 <- '4-2-5-1-'
6 <- '4-2-5-1-'
6 -- '4-2-5-1-6-'
6 -> '4-2-5-1-6-'
3 -- '4-2-5-1-6-3-'
7 <- '4-2-5-1-6-3-'
7 -- '4-2-5-1-6-3-7-'
8 <- '4-2-5-1-6-3-7-'
8 -- '4-2-5-1-6-3-7-8-'
8 -> '4-2-5-1-6-3-7-8-'
7 -> '4-2-5-1-6-3-7-8-'
3 -> '4-2-5-1-6-3-7-8-'
1 -> '4-2-5-1-6-3-7-8-'
缩进显示堆栈的深度。每个单独的递归调用有三个部分——左边的孩子、self.data和右边的孩子。
代码“知道”2在4之后,因为4发生在2调用的开始处,字符串'2-'
紧跟其后:
2 <- '' # start of 2's call. 2 starts by calling 4
4 <- '' # start of 4's call
4 -- '4-' # 4 appends self.data
4 -> '4-' # end of 4's call, returning to 2
2 -- '4-2-' # 2 appends self.data to what it got from 4, and calls 5
5 <- '4-2-' # start of 5's call
5 -- '4-2-5-' # 5 appends self.data
5 -> '4-2-5-' # end of 5's call, returning to 2
2 -> '4-2-5-' # end of 2's call
用递归方式遍历二叉树 思路说明 遍历二叉树的方法有广度优先和深度优先两类,下面阐述的是深度优先。 以下图的二叉树为例: 先定义三个符号标记: 访问结点本身(N) 遍历该结点的左子树(L) 遍历该结点的右子树(R) 有四种方式: 前序遍历(PreorderTraversal,NLR):先访问根结点,然后遍历其左右子树 中序遍历(InorderTraversal,LNR):先访问左子树,然后访问根节点
主要内容:递归实现,非递归实现二叉树后序遍历的实现思想是:从根节点出发,依次遍历各节点的左右子树,直到当前节点左右子树遍历完成后,才访问该节点元素。 图 1 二叉树 如图 1 中,对此二叉树进行后序遍历的操作过程为: 从根节点 1 开始,遍历该节点的左子树(以节点 2 为根节点); 遍历节点 2 的左子树(以节点 4 为根节点); 由于节点 4 既没有左子树,也没有右子树,此时访问该节点中的元素 4,并回退到节点 2 ,遍
主要内容:递归实现,非递归实现二叉树中序遍历的实现思想是: 访问当前节点的左子树; 访问根节点; 访问当前节点的右子树; 图 1 二叉树 以图 1 为例,采用中序遍历的思想遍历该二叉树的过程为: 访问该二叉树的根节点,找到 1; 遍历节点 1 的左子树,找到节点 2; 遍历节点 2 的左子树,找到节点 4; 由于节点 4 无左孩子,因此找到节点 4,并遍历节点 4 的右子树; 由于节点 4 无右子树,因此节点 2 的左子
主要内容:递归实现,非递归实现二叉树先序遍历的实现思想是: 访问根节点; 访问当前节点的左子树; 若当前节点无左子树,则访问当前节点的右子树; 图 1 二叉树 以图 1 为例,采用先序遍历的思想遍历该二叉树的过程为: 访问该二叉树的根节点,找到 1; 访问节点 1 的左子树,找到节点 2; 访问节点 2 的左子树,找到节点 4; 由于访问节点 4 左子树失败,且也没有右子树,因此以节点 4 为根节点的子树遍历完成。但节点
我有一些递归遍历二叉树的代码。 我需要一些帮助来了解正在发生的事情。我了解递归,我知道如何以迭代的顺序遍历二叉树,但似乎看不到这个递归解决方案的效果。 因此,如果'节点'不是无,我们将调用node.left递归函数,直到我们到达一个前导节点,在这种情况下node.left是无,然后我们移动到下一行'result.append(node.val)'? - 这对吗? 然后在“节点”上调用递归函数。对吧
我试图理解二叉树遍历(PreOrder)的实现。非递归方法很好,但我在试图理解递归方法时完全迷失了方向。 代码: 二叉树 我的理解是,当到达节点2(8-4-2)时,节点2的左边没有。所以条件将失败。 下面是我的问题。 点头之后。左无,右无。右边是横穿的?(因为如果启动:条件失败) 在节点1之后,逻辑如何移动到节点5哪个根节点。对吧? 我对递归的理解很差,请帮助!