一、二叉树的前序遍历
1.1 题目
给你二叉树的根节点 root
,返回它节点值的 前序 遍历。
示例 1:
输入:root = [1,null,2,3] 输出:[1,2,3]
示例 2:
输入:root = [] 输出:[]
示例 3:
输入:root = [1] 输出:[1]
示例 4:
输入:root = [1,2] 输出:[1,2]
示例 5:
输入:root = [1,null,2] 输出:[1,2]
提示:
- 树中节点数目在范围
[0, 100]
内 -100 <= Node.val <= 100
1.2 题目链接
1.3 解题思路和过程想法
(1)解题思路
1)递归:另需开辟一个递归函数。(递归函数的参数和返回值+终止条件+单层递归的逻辑)
2)易理解的非递归:要处理的就是当前结点。
3)统一形式的非递归:整体思路也是利用栈的属性,逆向压栈,最后弹出得出最终结果。但是“在要处理的结点放入栈之后,紧接着放入一个空指针作为标记”:其实就是在每个“小树”的根结点入栈后,放一个空指针在其后端作为标记——毕竟每一课小树都一定会有根结点,便于后续以合适的节奏弹出结点。
(2)过程想法:
递归是简单的,但想通其底层用栈的原理是难的。
1.4 代码
1.4.1 递归
# 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 Traverse(self,root:TreeNode,res:list):
# 前序遍历:根左右
if root:
res.append(root.val)
self.Traverse(root.left,res)
self.Traverse(root.right,res)
else:
return
def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
# 用来存结果的列表
res = []
self.Traverse(root,res)
return res
1.4.2 非递归(迭代)--用栈遍历(易理解)
class Solution:
def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
# 利用栈凭借非递归方式实现前序遍历
mystack = []
res = []
# 根结点 ---> 弹出 ---> 右结点 ---> 左结点 ---> 弹出 ---> 弹出
# 最后从结果数组中获取的就是:根左右
mystack.append(root)
while len(mystack):
# 弹出根结点,将其加入结果列表
node = mystack[-1]
mystack.pop()
if node:
res.append(node.val)
# 压入右结点
if node.right:
mystack.append(node.right)
# 压入左结点
if node.left:
mystack.append(node.left)
return res
1.4.3 统一形式的非递归
class Solution:
def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
# 统一的迭代方式实现遍历
mystack = []
res = []
# 保证二叉树非空,以进入下列循环
if root:
mystack.append(root)
# 利用栈来正序输出:根左右 ----> 逆向压栈:右左根
while len(mystack):
node = mystack[-1]
if node:
mystack.pop()
# 右
if node.right:
mystack.append(node.right)
# 左
if node.left:
mystack.append(node.left)
# 根 + 用 None 标记未处理结点
mystack.append(node)
mystack.append(None)
else:
# 若当前结点为空,则先弹出该空指针;再弹出未处理的“根”结点
mystack.pop()
node = mystack[-1]
mystack.pop()
res.append(node.val)
return res
二、二叉树的后序遍历
2.1 题目
给你一棵二叉树的根节点 root
,返回其节点值的 后序遍历 。
示例 1:
输入:root = [1,null,2,3] 输出:[3,2,1]
示例 2:
输入:root = [] 输出:[]
示例 3:
输入:root = [1] 输出:[1]
提示:
- 树中节点的数目在范围
[0, 100]
内 -100 <= Node.val <= 100
2.2 题目链接
2.3 解题思路和过程想法
(1)解题思路
1)递归:另需开辟一个递归函数。(递归函数的参数和返回值+终止条件+单层递归的逻辑)
2)易理解的非递归:要处理的就是当前结点。
3)统一形式的非递归:整体思路也是利用栈的属性,逆向压栈,最后弹出得出最终结果。但是“在要处理的结点放入栈之后,紧接着放入一个空指针作为标记”:其实就是在每个“小树”的根结点入栈后,放一个空指针在其后端作为标记——毕竟每一课小树都一定会有根结点,便于后续以合适的节奏弹出结点。
(2)过程想法:
递归是简单的,但想通其底层用栈的原理是难的。
2.4 代码
2.4.1 递归
# 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 postTraverse(self,root:TreeNode,res:list):
# 后续遍历:左右根
if root:
self.postTraverse(root.left,res)
self.postTraverse(root.right,res)
res.append(root.val)
else:
return
def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
# 用来存储结果
res = []
self.postTraverse(root,res)
return res
2.4.2 非递归(迭代) ---用指针遍历(易理解)
class Solution:
def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
mystack = []
# 用来存储结果
res = []
mystack.append(root)
# 根结点 ---> 压栈+弹出 ---> 左结点 ---> 压栈 ---> 右结点 ---> 压栈 ---> 弹出全部
# 最终结果:根右左 ---> 逆转:左右根
while len(mystack):
node = mystack[-1]
mystack.pop()
if node:
if node.left:
mystack.append(node.left)
if node.right:
mystack.append(node.right)
res.append(node.val)
res.reverse()
return res
2.4.3 统一形式的非递归
class Solution:
def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
# 统一的迭代方式实现遍历
mystack = []
res = []
# 保证二叉树非空,以进入下列循环
if root:
mystack.append(root)
# 利用栈来正序输出:左右根 ----> 逆向压栈:根右左
while len(mystack):
node = mystack[-1]
if node:
mystack.pop()
# 根 + 用 None 标记未处理结点
mystack.append(node)
mystack.append(None)
# 右
if node.right:
mystack.append(node.right)
# 左
if node.left:
mystack.append(node.left)
else:
# 若当前结点为空,则先弹出该空指针;再弹出未处理的“根”结点
mystack.pop()
node = mystack[-1]
mystack.pop()
res.append(node.val)
return res
三、二叉树的中序遍历
3.1 题目
给定一个二叉树的根节点 root
,返回 它的 中序 遍历 。
示例 1:
输入:root = [1,null,2,3] 输出:[1,3,2]
示例 2:
输入:root = [] 输出:[]
示例 3:
输入:root = [1] 输出:[1]
提示:
- 树中节点数目在范围
[0, 100]
内 -100 <= Node.val <= 100
3.2 题目链接
94.二叉树的中序遍历
3.3 解题思路和过程想法
(1)解题思路
1)递归:另需开辟一个递归函数。(递归函数的参数和返回值+终止条件+单层递归的逻辑)
2)非递归:基于中序遍历的思想,要处理的就是当前结点的方式行不通,使用指针+栈的方式。先一直向左(一直压栈),直到为空,则弹出根结点,并加入右孩子。
3)统一形式的非递归:整体思路也是利用栈的属性,逆向压栈,最后弹出得出最终结果。但是“在要处理的结点放入栈之后,紧接着放入一个空指针作为标记”:其实就是在每个“小树”的根结点入栈后,放一个空指针在其后端作为标记——毕竟每一课小树都一定会有根结点,便于后续以合适的节奏弹出结点。
(2)过程想法:
递归是简单的,但想通其底层用栈的原理是难的。
3.4 代码
3.4.1 递归
# 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 inTraverse(self,root:TreeNode,res:list):
# 中序遍历:左根右
if root:
self.inTraverse(root.left,res)
res.append(root.val)
self.inTraverse(root.right,res)
else:
return
def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
# 用来存储结果
res = []
self.inTraverse(root,res)
return res
3.4.2 非递归(迭代)---用栈遍历(易理解)
class Solution:
def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
# 用来存储结果
res = []
# 用指针来遍历结点
cur = root
# 用栈来记录已遍历的结点
mystack = []
while cur or len(mystack):
# 一直向左
if cur:
mystack.append(cur)
cur = cur.left
# 左边走不下去,就弹出;并将右压栈
else:
node = mystack[-1]
mystack.pop()
res.append(node.val)
cur = node.right
return res
3.4.3 统一形式的非递归
class Solution:
def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
# 统一的迭代方式实现遍历
mystack = []
res = []
# 保证二叉树非空,以进入下列循环
if root:
mystack.append(root)
# 利用栈来正序输出:左根右 ----> 逆向压栈:右根左
while len(mystack):
node = mystack[-1]
if node:
mystack.pop()
# 右
if node.right:
mystack.append(node.right)
# 根 + 用 None 标记未处理结点
mystack.append(node)
mystack.append(None)
# 左
if node.left:
mystack.append(node.left)
else:
# 若当前结点为空,则先弹出该空指针;再弹出未处理的“根”结点
mystack.pop()
node = mystack[-1]
mystack.pop()
res.append(node.val)
return res