目录
二叉树的前、中、后序遍历(递归&迭代)
定义二叉树
# 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 preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
def preorder(node):
if node== None:
return
res.append(node.val)
preorder(node.left)
preorder(node.right)
res = []
preorder(root)
return res
中序(左根右)
class Solution:
def inorderTraversal(self, root: TreeNode) -> List[int]:
def inorder(node):
if node==None:
return
inorder(node.left)
res.append(node.val)
inorder(node.right)
res = []
inorder(root)
return res
以上图二叉树为例,中序递归过程如下:
inorder(root)
- inorder(1)入栈---> inorder(2)入栈---〉inorder(4)入栈,4无左右子树,开始出栈(后入先出
- inorder(4)出栈,res [4] ---> inorder[2]出栈,res [4,2],2存在右子树,右子树5入栈,此时栈中还剩inorder(1)
- inorder(5)入栈,5无左右子树,开始出栈
- inorder(5)出栈,res[4,2,5] ---> inorder(1)出栈,res[4,2,5,1],1存在右子树,右子树3入栈,注意此时栈已清空
- inorder(3)入栈 ---> inorder(6)入栈,6无左右子树,开始出栈
- inorder(6)出栈,res[4,2,5,1,6] --->inorder(3)出栈,res[4,2,5,1,6,3],3存在右子树,右子树7入栈
- inorder(7)入栈,7无左右子树,开始出栈
- inorder(7)出栈,res[4,2,5,1,6,3,7]
res [4,2,5,1,6,3,7]
后序(左右根)
class Solution:
def postorderTraversal(self, root: TreeNode) -> List[int]:
def postorder(node):
if node == None:
return
postorder(node.left)
postorder(node.right)
res.append(node.val)
res = []
postorder(root)
return res
迭代(难度:中等)
迭代其实就是递归的显式表达,根据上述中序递归的详细过程可以看出来递归是隐性维护一个栈进行迭代,而迭代的方法是维护栈的显式过程。
前序(根左右)
维护栈(后入先出),入栈顺序:先右后左
1. 根入栈
2. 出栈
3. (步骤a)右子树、左子树顺序入栈
4. (步骤b)出栈
5. 循环(步骤a)(步骤b),直至栈被清空
class Solution:
def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
def pull_root(node):
if node:
stack.append(node)
stack, res = [], []
pull_root(root) #初始根入栈
while stack:
node = stack.pop()
res.append(node.val)
pull_root(node.right) #右先入栈
pull_root(node.left) #左后入栈
return res
中序(左根右)
维护栈(后入先出),
1. 最左叶子全部入栈(左节点压在栈底)
2. 出栈,若栈顶有右节点,右的所有左节点入栈(体会下这一步就是先右后左)
class Solution:
def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
def pull_all_left(node):
while node:
stack.append(node)
node = node.left
stack, res = [], []
pull_all_left(root)
while stack:
node = stack.pop()
res.append(node.val)
pull_all_left(node.right)
return res
后序(左右根)
可以看作“根右左”的反转,迭代思想同前序
class Solution:
def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
def pull_root(node):
if node:
stack.append(node)
stack, res = [], []
pull_root(root) #初始根入栈
while stack:
node = stack.pop()
res.append(node.val)
pull_root(node.left) #左先入栈
pull_root(node.right) #右后入栈
return res[::-1] #翻转