二叉树的前序、中序、后续遍历
前序、中序、后序指的是根输出的顺序
1.递归遍历
前序遍历:打印 -> 左 -> 右
中序遍历:左 -> 打印 -> 右
后序遍历:左 -> 右 -> 打印
1.1递归前序遍历
from typing import List
class Solution:
def preorderTraversal(self, root: TreeNode) -> List[int]:
path = []
def dfs(tree_node):
if not tree_node:
return
path.append(tree_node.val)
dfs(tree_node.left)
dfs(tree_node.right)
dfs(root)
return path
1.2递归中序遍历
终止条件:当前节点为空
函数内:递归的调用左节点,打印当前节点,再递归调用右节点
时间复杂度:O(n)
空间复杂度:O(h),h是树的高度
from typing import List
class Solution:
def inorderTraversal(self, root: TreeNode) -> List[int]:
path = []
def dfs(tree_node):
if not tree_node:
return
dfs(tree_node.left)
path.append(tree_node.val)
dfs(tree_node.right)
dfs(root)
return path
1.3递归后序遍历
from typing import List
class Solution:
def postorderTraversal(self, root: TreeNode) -> List[int]:
path = []
def dfs(tree_node):
if not tree_node:
return
dfs(tree_node.left)
dfs(tree_node.right)
path.append(tree_node.val)
dfs(root)
return path
2. 栈 + 迭代
递归实现时,是函数自己调用自己,一层层的嵌套下去,操作系统/虚拟机自动帮我们用栈来保存了每个调用的函数,现在我们需要自己模拟这样的调用过程
#栈 ,先进后出
# 前序遍历,出栈顺序:根左右
# 中序遍历,出栈顺序:左根右
# 后序遍历,出栈顺序:左右根
2.1迭代前序遍历
2.1.1模拟递归迭代过程的编码方式
from typing import List
class Solution:
def preorderTraversal(self, root: TreeNode) -> List[int]:
ans = []
stack = []
while stack or root:
if root:
ans.append(root.val)
stack.append(root)
root = root.left
else:
tmp = stack.pop()
root = tmp.right
return ans
2.1.2 利用进出栈顺序编程
前序遍历顺序: 中左右
用列表模拟栈: 栈 ->后进先出
故前序遍历 出栈顺序:中左右 入栈顺序:右左中
class Solution:
def preorderTraversal(self, root: TreeNode) -> List[int]:
ans = []
stack = []
if not root:
return ans
stack.append(root)
while stack:
tree_node = stack.pop()
#入栈顺序右左中
ans.append(tree_node.val)
if tree_node.right:
stack.append(tree_node.right)
if tree_node.left:
stack.append(tree_node.left)
return ans
#更好理解的前序迭代
class Solution:
def inorderTraversal(self, root: TreeNode) -> List[int]:
#列表模拟栈 ,先进后出
#前序、中序、后序指的是根输出的顺序
# 前序遍历,出栈顺序:根左右,入栈顺序:右左根
ans = []
stack = []
if root:
stack.append(root)
while stack:
node = stack.pop()
if node:
if node.right:#右
stack.append(node.right)
if node.left:#左
stack.append(node.left)
stack.append(node)#中
stack.append(None)
else:
node = stack.pop()
ans.append(node.val)
return ans
2.2 迭代中序遍历
2.2.1 模拟递归迭代过程
class Solution:
def inorderTraversal(self, root: TreeNode) -> List[int]:
ans = []
stack = []
while stack or root:
# 不断往左子树方向前进,每次前进将当前节点保存到栈中
# 模拟递归的调用
if root:
stack.append(root)
root = root.left
#当前节点为空时,说明左边走到头,从栈中弹出节点并保存
#然后转到右边节点,继续上面的过程
else:
tmp = stack.pop()
ans.append(tmp.val)
root = tmp.right
return ans
更好理解的中序迭代
class Solution:
def inorderTraversal(self, root: TreeNode) -> List[int]:
# 中序遍历,出栈顺序:左根右,入栈顺序:右根左
ans = []
stack = []
if root:
stack.append(root)
while stack:
node = stack.pop()
if node:
if node.right:#右
stack.append(node.right)
stack.append(node)#中
stack.append(None)#中节点访问过,但未处理,加入空节点做标记
if node.left:#左
stack.append(node.left)
else:
node = stack.pop()
ans.append(node.val)
return ans
2.3 迭代后序遍历
from collections import deque
from typing import List
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def make_tree(data):
if data == []:
return
root = TreeNode(data[0])
queue = deque([root])
i = 1
while i < len(data):
node = queue.popleft()
if data[i] != 'null':
node.left = TreeNode(data[i])
queue.append(node.left)
i = i + 1
if data[i] != 'null':
node.right = TreeNode(data[i])
queue.append(node.right)
i = i + 1
return root
class Solution:
def postorderTraversal(self, root: TreeNode) -> List[int]:
# 后序遍历,出栈顺序:左右根,入栈顺序:根右左
ans = []
stack = []
if root:
stack.append(root)
while stack:
node = stack.pop()
if node:
stack.append(node)#中节点访问过,但未处理,加入空节点做标记
stack.append(None)
if node.right:
stack.append(node.right)#右
if node.left:
stack.append(node.left)#左
else:
node = stack.pop()
ans.append(node.val)
return ans