为什么我遍历二叉树in-order的代码只记录第一个节点的值?
Why is my code to traverse binary tree in-order only recording the value of the first node?
我正在尝试编写代码来使用递归遍历二叉树 in-order,这是我的代码:
例如输入 = [1,null,2,3]
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def inorderTraversal(self, root: TreeNode) -> List[int]:
in_order = []
stack, curr = [], root
if not curr:
return None
else:
inorderTraversal(curr.left)
in_order.append(curr.val)
inorderTraversal(curr.right)
return in_order
由于某些原因,输出只记录了第一个节点的值!所以我得到 in_order=[1]
我怀疑它与 'else'
语句中的代码有关。谁能建议修改?谢谢
作为后续,基于提供的解决方案:
以下Binary tree
我想确保我理解正确,递归堆栈将存储 A,然后是 B,然后是 C。因为 C 没有 child(我们遇到了基本情况)。然后将C记录在in_order
中。然后我们从递归堆栈中弹出下一个项目 B,此时我们调用 inorderTraversal(root.left)
还是 inorderTraversal(root.right)
?
更一般地说,当我们从递归堆栈中弹出东西时,我们是否从第一个递归调用开始向下工作?
计算机是如何处理的?我了解 objects 是如何添加到递归堆栈的,但令人困惑的是当它们被弹出时,我们从哪里开始?因为我读它的方式是保存 A、B、C 的递归堆栈来自 inorderTraversal(root.left)
,所以这意味着当它们被弹出时我们应该向下移动到下一行 in_order.append(root.val)
;这样对吗?
对此有两种选择。您可以将数组传递到您附加的递归函数中。或者您可以 return 一个数组并将其与调用函数的组合。第一个可能性能更高,因为您不会一遍又一遍地移动相同的元素。但它并不那么漂亮。使用上面的代码,这里有一个建议的更改。
class Solution:
def inorderTraversal(self, root: TreeNode) -> List[int]:
in_order = []
if not root:
return []
else:
in_order.extend(self.inorderTraversal(root.left))
in_order.append(root.val)
in_order.extend(self.inorderTraversal(root.right))
return in_order
更新
要遍历 OP 中的树,以下是调用的样子。为了简洁起见,我将缩短对 R() 的函数调用,我将简单地通过它的值来引用树。缩进将象征递归堆栈的深度。
R(A)
R(B) # A.left
R(C) # B.left
R(C.left)
return []
Append(C)
R(.right)
return []
return [C] # R(C.left) + [C] + R(C.right)
Append(B)
R(D) # B.right
R(E) # D.left
Append(D)
R(D.right)
return []
return [E, D] # R(D.left) + [D] + R(D.right)
return [C, B, E, D] # R(B.left) + [B] + R(B.right)
Append(A)
R(G) # A.right
...
return [C, B, E, D, A, F, G, H] # R(A.left) + [A] + R(A.right)
您没有使用递归调用的结果(常见错误)。另一个答案已经涵盖了这一点。您可以使用生成器函数非常优雅地完成此操作,但是:
class Solution:
def inorderTraversal(self, root: TreeNode) -> List[int]:
def io(node):
if node:
yield from io(node.left)
yield node.val
yield from io(node.right)
return list(io(root))
我正在尝试编写代码来使用递归遍历二叉树 in-order,这是我的代码:
例如输入 = [1,null,2,3]
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def inorderTraversal(self, root: TreeNode) -> List[int]:
in_order = []
stack, curr = [], root
if not curr:
return None
else:
inorderTraversal(curr.left)
in_order.append(curr.val)
inorderTraversal(curr.right)
return in_order
由于某些原因,输出只记录了第一个节点的值!所以我得到 in_order=[1]
我怀疑它与 'else'
语句中的代码有关。谁能建议修改?谢谢
作为后续,基于提供的解决方案:
以下Binary tree
我想确保我理解正确,递归堆栈将存储 A,然后是 B,然后是 C。因为 C 没有 child(我们遇到了基本情况)。然后将C记录在in_order
中。然后我们从递归堆栈中弹出下一个项目 B,此时我们调用 inorderTraversal(root.left)
还是 inorderTraversal(root.right)
?
更一般地说,当我们从递归堆栈中弹出东西时,我们是否从第一个递归调用开始向下工作?
计算机是如何处理的?我了解 objects 是如何添加到递归堆栈的,但令人困惑的是当它们被弹出时,我们从哪里开始?因为我读它的方式是保存 A、B、C 的递归堆栈来自 inorderTraversal(root.left)
,所以这意味着当它们被弹出时我们应该向下移动到下一行 in_order.append(root.val)
;这样对吗?
对此有两种选择。您可以将数组传递到您附加的递归函数中。或者您可以 return 一个数组并将其与调用函数的组合。第一个可能性能更高,因为您不会一遍又一遍地移动相同的元素。但它并不那么漂亮。使用上面的代码,这里有一个建议的更改。
class Solution:
def inorderTraversal(self, root: TreeNode) -> List[int]:
in_order = []
if not root:
return []
else:
in_order.extend(self.inorderTraversal(root.left))
in_order.append(root.val)
in_order.extend(self.inorderTraversal(root.right))
return in_order
更新
要遍历 OP 中的树,以下是调用的样子。为了简洁起见,我将缩短对 R() 的函数调用,我将简单地通过它的值来引用树。缩进将象征递归堆栈的深度。
R(A)
R(B) # A.left
R(C) # B.left
R(C.left)
return []
Append(C)
R(.right)
return []
return [C] # R(C.left) + [C] + R(C.right)
Append(B)
R(D) # B.right
R(E) # D.left
Append(D)
R(D.right)
return []
return [E, D] # R(D.left) + [D] + R(D.right)
return [C, B, E, D] # R(B.left) + [B] + R(B.right)
Append(A)
R(G) # A.right
...
return [C, B, E, D, A, F, G, H] # R(A.left) + [A] + R(A.right)
您没有使用递归调用的结果(常见错误)。另一个答案已经涵盖了这一点。您可以使用生成器函数非常优雅地完成此操作,但是:
class Solution:
def inorderTraversal(self, root: TreeNode) -> List[int]:
def io(node):
if node:
yield from io(node.left)
yield node.val
yield from io(node.right)
return list(io(root))