题目:144.二叉树的前序遍历
题目:94.二叉树的中序遍历
代码来源:
一般这种题目有两种方法:递归和迭代
(递归和迭代有什么区别呢?这个问题还不太懂,希望之后能理解)
第一种:递归方法
思路:
-
要知道“前序遍历”是如何遍历的——根、左、右,“中序遍历”——左、根、右
-
根据这种遍历的方法,定义递归函数:
(1)把跳出递归函数的条件放在最前面——if not node: return
;
(2)根据前序遍历的定义:
a.给result
先插入根节点的值——result.append(node.val)
;
b.再去处理左子树(左节点)——helper(node.left)
;
c.最后处理右子树(右节点)——helper(node.right)
; -
思考:如果是“中序遍历”、“后序遍历”,根据递归的方法如何写代码呢?
——是不是只需要将2.(2)中三行代码的顺序调整一下即可?
——根据中序遍历的定义:
a.先处理左子树(左节点)——helper(node.left
;
b.给result
先插入根节点的值——result.append(node.val)
;
c.最后处理右子树(右节点)——helper(node.right)
;
前序遍历-具体代码:
class Solution(object):
def preorderTraversal(self, root):
"""
:type root: TreeNode
:rtype: List[int]
"""
# 递归
result = []
# 定义一个用于递归的函数
def helper(node):
# 当节点为None的时候,直接返回result
if not node:
return
result.append(node.val) # 根节点的值
helper(node.left) # 左子树(左节点)
helper(node.right) # 右子树(右节点)
# 调用函数进行递归
helper(root)
return result
中序遍历-具体代码:
class Solution(object):
def inorderTraversal(self, root):
"""
:type root: TreeNode
:rtype: List[int]
"""
# 递归
result = []
def helper(node):
# 当节点为None的时候,直接返回result
if not node:
return
helper(node.left) # 左节点/左子树
result.append(node.val) # 根节点
helper(node.right) # 右节点/右子树
helper(root)
return result
第二种:迭代的方法
前序遍历的思路
- 首先,特殊情况,根节点如果不存在,则返回空列表:
if not root: return []
- 定义
result
用来存放最后输出的节点值,定义stack
——用栈来存取节点 - 关于栈,我们一定要知道“后进先出”的规则,因此根据“根、左、右”的前序遍历:
(1)我们需要先定义栈的初始值:stack = [root]
;
(2)取出node = stack.pop()
,将其值加入result
列表中;
(3)再对该节点进行判断,是否存在左右节点 - 注意!!
(1)一定要先判断右节点是否存在,先将右节点压入栈内,再将左节点压入栈内;
(2)这样利用node = stack.pop()
取出最后一个元素的时候,先将左节点取出,再将右节点取出,正好符合我们“前序遍历——根、左、右”的规则;
前序遍历-具体代码:
class Solution(object):
def preorderTraversal(self, root):
"""
:type root: TreeNode
:rtype: List[int]
"""
# 迭代
# 如果根节点不存在,则返回[]
if not root:
return []
# 定义result用来存放每个节点的值
result = []
# 定义stack用来存放节点以及删除节点
stack = [root]
while stack:
node = stack.pop() # 删除栈中最后一个元素
result.append(node.val)
# 先压入右子树
if node.right:
stack.append(node.right)
# 再压入左子树
if node.left:
stack.append(node.left)
return result
中序遍历的思路
- 一开始并没有要去判断root是否为空,因为后面的循环有对root的判断;
- 定义
result=[]
,stack=[]
,如果stack
和root
都为空的话,第一个循环就结束了; - 第二个循环
while root:
,是为了不断压入左子树的左节点,使得stack
中的顶点是树中最左边的节点; - 取出
stack
中的顶点,即最左边的节点,将其值插入result
中
(1)第一次循环的这个root = stack.pop()
,肯定是没有左节点的;
(2)但是可能有右节点/右子树,所以要令root=root.right
将右边的节点依此压入stack
中,再依此的取出来,插入结果中。
具体的动画演示
中序遍历-具体代码:
class Solution(object):
def inorderTraversal(self, root):
"""
:type root: TreeNode
:rtype: List[int]
"""
# 迭代
result = []
stack = [] # 用来存储根节点左子树
while stack or root:
# 先给栈压入所有的左子树
while root:
stack.append(root)
root = root.left
# 当已经到了最左边的时候,root=None,跳出循环
root = stack.pop() # 先取出栈中的顶点
result.append(root.val)
# 如果存在右节点,将右子树的节点压入栈中
# 如果右节点不存在的话,root=None
root = root.right
return result