1. 前言
在做二叉樹相關的算法題時,常常會遇到二叉樹的遍歷問題。而二叉樹的遍歷有4中方式,這4種方式都有其遞歸實現和迭代實現,本文僅記錄這4種遍歷方式的遞歸實現和迭代實現。
2. 深度優先遍歷(DFS)
DFS有三種,前序遍歷
,中序遍歷
和後序遍歷
。這3種遍歷方式是基於根節點的先後而言的。
2.1 前序遍歷
以根-左-右
的順序遍歷二叉樹中的節點。遍歷順序爲:A-B-D-E-C-F-G
特點是,第一個節點爲二叉樹的根節點,子樹也滿足此規律。
- 根節點A加入棧中,棧爲 [A];
- 從棧中彈出節點A,將節點A的右子節點C和左子節點B依次入棧,此時棧爲 [C, B];
- 從棧中彈出節點B,將節點B的右子節點E和左子節點D依次入棧,此時棧爲 [C, E, D];
- 從棧中彈出節點D,沒有左子節點,此時棧爲 [C, E];
- 繼續上述步驟。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def pre_order(self, root):
"""
遞歸實現
"""
if not root: return
print(root.val)
self.pre_order(self, root.left)
self.pre_order(self, root.right)
def pre_order(self, root):
"""
迭代實現,推薦使用
"""
if not root: return []
result = []
stack = [root]
while stack:
node = stack.pop()
result.append(node.val)
# 先加入右,再加左,因爲LIFO
if node.right: stack.append(node.right)
if node.left: stack.append(node.left)
return result
2.2 中序遍歷
以左-根-右
的順序遍歷二叉樹中的節點。遍歷順序爲:D-B-E-A-F-C-G
特點是,根節點左邊的節點都在左子樹,根節點右邊的節點都在右子樹,子樹也滿足此規律。
- 有左就往左走,直到當前節點的最左子節點;
- 有右就往右走1步,再重複第1步,否則回溯到父節點,再重複第1步;
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def in_order(self, root):
"""
遞歸實現
"""
if not root: return
self.in_order(self, root.left)
print(root.val)
self.in_order(self, root.right)
def in_order(self, root):
"""
迭代實現
"""
result = []
stack = []
while root or stack:
# 1. 有左就往左走,直到最左子節點
while root:
stack.append(root)
root = root.left
# 2. 有右就往向右走1步,在重複第1步
root = stack.pop()
result.append(root.val)
root = root.right
return result
2.3 後序遍歷
以左-右-根
的順序遍歷二叉樹中的節點。遍歷順序爲:D-E-B-F-G-C-A
特點是,最後一個節點爲根節點,子樹也滿足此規律。
因爲先序遍歷的順序是 根-左-右, 後序遍歷的順序是 左-右-根。
採用先序遍歷的變形,首先實現一個根-右-左的遍歷,然後將其壓入輔助棧中,最後依次將輔助棧中的元素彈出即可。
例子中,根-右-左的遍歷順序爲:A-C-G-F-B-E-D
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def last_order(self, root):
"""
遞歸實現
"""
if not root: return
self.last_order(self, root.left)
self.last_order(self, root.right)
print(root.val)
def last_order(self, root):
"""
迭代實現
"""
if not root: return []
result = []
stack = [root]
while stack:
node = stack.pop()
result.append(node.val)
# 先入左,再入右
if node.left: stack.append(node.left)
if node.right: stack.append(node.right)
result.reverse() # 逆序,將根-右-左變換爲左-右-根
return result
3. 廣度優先遍歷(BFS)
廣度優先遍歷也就是我們常說的層序遍歷
。遍歷順序爲:A-B-C-D-E-F-G
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def bfs(self, root):
"""
迭代實現版本1
層序遍歷
"""
if not root: return
result = []
queue = [root]
while queue:
node = queue.pop(0)
result.append(node.val)
if node.left: queue.append(node.left)
if node.right: queue.append(node.right)
return result
def bfs(self, root):
"""
迭代實現版本2。這兩者的區別是,版本2能夠獲取具體每一層的數據,而版本1的混在一起的。
層序遍歷
"""
if not root: return
result = []
queue = [root]
while queue:
next_level = [] # 記錄下一層的節點
while queue:
node = queue.pop(0)
result.append(node.val)
if node.left: next_level.append(node.left)
if node.right: next_level.append(node.right)
queue = next_level
return result
總結
本文僅是記錄二叉樹的實現,免得忘了之後又得在網上找半天。