先序: 左右根
中序: 左根右
後序: 左右根
先說遞歸:
先序:
def preTraversal(self, root: TreeNode) -> List[int]:
res = []
def dfs(root):
if root:
res.append(root.val) # 通路根節點
dfs(root.left) # 遞歸左
dfs(root.right) # 遞歸右
dfs(root)
return
中序:
def inorderTraversal(self, root: TreeNode) -> List[int]:
res = []
def dfs(root):
if root:
dfs(root.left)
res.append(root.val)
dfs(root.right)
dfs(root)
return
後序:
def laterTraversal(self, root: TreeNode) -> List[int]:
res = []
def dfs(root):
if root:
dfs(root.left)
dfs(root.right)
res.append(root.val)
dfs(root)
return
疊代:
先序:
class Solution:
def preorderTraversal(self, root: TreeNode) -> List[int]:
if not root:return []
res, stack = [], []
while root or stack: # stack為空且node為null時,說明周遊結束
while root: # 可以進入左子樹時,先通路,再進入
res.append(root.val)
stack.append(root)
root = root.left
root = stack.pop()
root = root.right # 否則進入棧中節點的右子樹
return
中序:
class Solution:
def inorderTraversal(self, root: TreeNode) -> List[int]:
if not root: return [] # 若root為空則直接傳回空
res, stack = [], []
while root or stack: # stack為空且root為null時,說明已經周遊結束
while root: # 可以深入左子樹
stack.append(root)
root = root.left
root = stack.pop() # 否則通路棧中節點,并深入右子樹
res.append(root.val)
root = root.right
return
後序:
class Solution:
def postorderTraversal(self, root: TreeNode) -> List[int]:
if not root: return []
res, stack = [], []
prev = None
# prev記錄剛剛通路的節點,
# 如果目前通路節點是上次通路節點的父節點,則說明子樹通路完成,可以通路目前節點了。
while root or stack:
while root:
stack.append(root)
root = root.left
root = stack.pop()
# 比前序和中序的模闆增加一個判斷過程:節點沒有右孩子或已經通路了該節點的子節點
if not root.right or root.right == prev:
res.append(root.val)
prev = root
root = None # 這裡root必須要重新設定成None
# 因為走到這一步的時候,左右都已經是空的了。
# 預防再次循環的時候root進入到一開始的那個while
else: # 存在右孩子沒周遊
stack.append(root)
root = root.right
return
後序稍微加了一個判斷子產品。畫個樹,手動模拟一下就了解了。
注釋都寫在代碼裡了,看一下就懂了~
另外兩中方法的時間複雜度.