二叉樹有四種種常見的遍歷方式:
前序遍歷:按照根—>左子樹——>右子樹的遞歸方式進行遍歷
中序遍歷:按照左子樹—>根——>右子樹的遞歸方式進行遍歷
後序遍歷:按照左子樹—>右子樹——>根的遞歸方式進行遍歷
層次遍歷:採用逐層的方式進行遍歷
下面分別就上述四種遍歷方式給出遞歸解法和非遞歸的解法。
1. 前序遍歷
- 遞歸方式
以節點爲單位進行遞歸,遞歸函數爲子樹根節點入列+左子樹遞歸+右子樹遞歸。遞歸終止條件爲到達葉子節點,無子樹。
def preorder_traversal(t:BinaryTree, stores=[]):
if t:
stores.append(t.getRootVal())
preorder_traversal(t.getLeftChild(), stores)
preorder_traversal(t.getRightChild(), stores)
return stores
- 非遞歸方式
作爲一種DFS,採用棧+循環的方式進行遍歷。核心思想爲:將子樹根節點彈出,依次壓入右子樹根節點和左子樹根節點。
def preorder_traversal(t: BinaryTree):
if t.key is None:
return None
root = t
stack = Stack() # 存放節點棧
nodes = [] # 存放結果
stack.push(root)
while not stack.isEmpty():
current = stack.pop()
if current.getRightChild():
stack.push(current.getRightChild())
if current.getLeftChild():
stack.push(current.getLeftChild())
nodes.append(current.key)
return nodes
2. 中序遍歷
- 遞歸方式
以節點爲單位進行遞歸,遞歸函數爲左子樹遞歸+子樹根節點入列+右子樹遞歸。遞歸終止條件爲到達葉子節點,無子樹。
def midorder_traversal(t: BinaryTree, stores=[]):
if t:
midorder_traversal(t.getLeftChild(), stores)
stores.append(t.getRootVal())
midorder_traversal(t.getRightChild(),stores)
return stores
- 非遞歸方式
作爲一種DFS,仍採用棧+循環的方式進行遍歷。核心思想爲:先將左子樹全部壓入棧堆,然後作爲根節點彈出,若根節點存在右子樹,重複上述過程,否則回溯到上層的根節點。
def midorder_traversal(t: BinaryTree):
if t.key is None:
return None
current = t
stack = Stack() # 存放節點棧
nodes = [] # 存放結果
while current is not None or not stack.isEmpty():
if current is not None:
stack.push(current)
current = current.getLeftChild()
else:
current = stack.pop()
nodes.append(current.key)
current = current.getRightChild()
return nodes
3. 後序遍歷
- 遞歸方式
以節點爲單位進行遞歸,遞歸函數爲左子樹遞歸+右子樹遞歸+子樹根節點入列。遞歸終止條件爲到達葉子節點,無子樹。
def postorder_traversal(t: BinaryTree, stores=[]):
if t:
postorder_traversal(t.getLeftChild(), stores)
postorder_traversal(t.getRightChild(),stores)
stores.append(t.getRootVal())
return stores
- 非遞歸方式
後序遍歷可視爲前序遍歷的變種(根節點——>右子樹——>左子樹)的轉置。因此可以在前序遍歷的基礎上直接逆序結果。
def postorder_traversal(t: BinaryTree):
if t.key is None:
return None
root = t
stack = Stack()
nodes = []
stack.push(root)
while not stack.isEmpty():
current = stack.pop()
if current.getLeftChild():
stack.push(current.getLeftChild())
if current.getRightChild():
stack.push(current.getRightChild())
nodes.append(current.key)
return list(reversed(nodes))
4. 層次遍歷
- 遞歸方式
以一層根節點爲單位進行遞歸,遞歸函數爲本層節點數據+下一層根節點的遞歸節點入列。遞歸終止條件爲到達最下面一層葉子節點。
def levelorder_traversal(level_trees=[], stores=[]):
next_level_trees = []
if level_trees:
for t in level_trees:
stores.append(t.getRootVal())
if t.getLeftChild():
next_level_trees.append(t.getLeftChild())
if t.getRightChild():
next_level_trees.append(t.getRightChild())
levelorder_traversal(next_level_trees, stores)
return stores
- 非遞歸方式
採用隊列的方式對每層節點進行出列,同時對這些節點的左、右子樹進行入列操作。
def levelorder_traversal(t: BinaryTree):
if t.key is None:
return None
root = t
quene = Quene()
nodes = []
quene.enquene(root)
while not quene.isEmpty():
current = quene.dequene()
if current.getLeftChild():
quene.enquene(current.getLeftChild())
if current.getRightChild():
quene.enquene(current.getRightChild())
nodes.append(current.key)
return nodes
上述代碼依賴的基本數據結構包括:
- 二叉樹
class BinaryTree(object):
def __init__(self, rootObj):
self.key = rootObj
self.leftChild = None
self.rightChild = None
# 插入左子數
def insertLeft(self, newBranch):
if self.leftChild is None:
self.leftChild = BinaryTree(newBranch)
else:
t = BinaryTree(newBranch)
t.leftChild = self.leftChild
self.leftChild = t
# 插入右子樹
def insertRight(self, newBranch):
if self.rightChild is None:
self.rightChild = BinaryTree(newBranch)
else:
t = BinaryTree(newBranch)
t.rightChild = self.rightChild
self.rightChild = t
# 獲取根節點值
def getRootVal(self):
return self.key
# 設置根節點值
def setRootVal(self, value):
self.key = value
# 獲取左子樹
def getLeftChild(self):
return self.leftChild
# 獲取右子樹
def getRightChild(self):
return self.rightChild
- 棧
class Stack(object):
def __init__(self):
self.head = None
def push(self, value):
node = Node(value)
if self.head is None:
self.head = node
else:
node.next = self.head
self.head = node
def pop(self):
if self.isEmpty():
raise IndexError("pop from empty stack")
else:
node = self.head.value
self.head = self.head.next
return node
def isEmpty(self):
return self.head is None
- 隊列
class Quene(object):
def __init__(self):
self.head = None
def __repr__(self):
data = []
current = self.head
if current is None:
return None
else:
while current:
data.append(current.value)
current = current.next
return str(data)
def enquene(self, value):
# 入隊列
new_node = Node(value)
if self.isEmpty():
self.head = new_node
else:
current = self.head
while current.next is not None:
current = current.next
current.next = new_node
def dequene(self):
# 出隊列
if self.isEmpty():
raise IndexError("dequene from empty quene")
else:
current = self.head
self.head = self.head.next
return current.value
def isEmpty(self):
return self.head is None