前面一篇我們介紹了二叉樹的廣度優先添加和周遊元素,在二叉樹的周遊技術中,除了廣度優先周遊,還有一種叫深度優先周遊。本篇就來讨論深度周遊的三種重要的方法,它們分别是先序周遊和中序周遊和後序周遊。
1.三種深度周遊的概念
深度周遊有重要的三種方法,這三種方式常被用于通路樹的節點。它們之間不同在于通路每個節點的次序不同。這三種周遊分别叫做先序周遊(preorder),中序周遊(inorder)和後序周遊(postorder).
先序周遊
在先序周遊中,我們先通路根節點,然後遞歸使用先序周遊通路左子樹,再遞歸使用先序周遊通路右子樹。
根節點->左子樹->右子樹
中序周遊
遞歸使用中序周遊先通路左子樹,然後通路根節點,最壞遞歸使用中序通路右子樹。
左子樹->根節點->右子樹
後序周遊
遞歸使用後序周遊先通路左子樹,然後遞歸使用後序周遊通路右子樹,最後通路根節點。
左子樹->右子樹->根節點
2.具體一顆二叉樹的三種深度周遊分析
下面給出一個具體二叉樹,然後我們利用上面的概念,來寫出周遊輸出元素的順序。

這個按照前面的廣度優先周遊輸出元素的順序是:0 1 2 3 4 5 6 7 8 9
先序周遊
先序周遊順序是先根節點,然後左子樹,然後右子樹。我們這裡拿先序周遊重點介紹這個思路分析過程。
第一步,周遊根節點,輸出 0
第二步,發現左節點1下形成一個左子樹,右邊節點2也是一顆樹。左子樹優先右子樹周遊,是以第二個輸出 1
第三步,周遊發現3 4節點,左子樹優先元素,輸出 3
第四步,周遊7 8 節點,輸出7
第五步,在 378這個子樹,剩下8這個右節點,是以輸出 8
第六步,因為3節點已經周遊過,這裡周遊輸出 4
第七步,4節點的隻有9這個節點,輸出 9
第八步,到這裡 1節點下左子樹全部周遊完成,這裡開始周遊2子樹,這裡輸出 2
第九步,5 6節點,左邊優先,輸出 5
第十步,輸出 6
是以先序周遊輸出元素順序為:0 1 3 7 8 4 9 2 5 6
中序周遊
根據遇到一棵樹,先左子樹->根節點-右子樹規則
周遊元素順序為:7 3 8 1 9 4 0 5 2 6
後序周遊
根據遇到一棵樹,先左子樹->右子樹->根節點 規則
周遊元素順序為:7 8 3 9 4 1 5 6 2 0
3.代碼實作三種深度周遊
下面接着上一篇python代碼,來寫先序 中序 後序三種周遊的代碼。
先序周遊實作
# coding:utf-8
class Node(object):
"""節點"""
def __init__(self, itme):
self.ele = itme
self.lchild = None
self.rchild = None
class BinaryTree(object):
"""二叉樹"""
def __init__(self):
self.root = None
def add(self, item):
node = Node(item)
if self.root is None:
self.root = node
return
# 一個隊列,添加根元素
queue = [self.root]
while queue:
cur_node = queue.pop(0)
if cur_node.lchild is None:
cur_node.lchild = node
return
else:
queue.append(cur_node.lchild)
if cur_node.rchild is None:
cur_node.rchild = node
return
else:
queue.append(cur_node.rchild)
def breadth_travle(self):
"""廣度周遊"""
if self.root is None:
return
queue = [self.root]
while queue:
cur_node = queue.pop(0)
print(cur_node.ele, end=" ")
if cur_node.lchild is not None:
queue.append(cur_node.lchild)
if cur_node.rchild is not None:
queue.append(cur_node.rchild)
def preorder(self, node):
"""先序周遊,node 是根節點"""
if node is None:
return
print(node.ele, end=" ")
self.preorder(node.lchild)
self.preorder(node.rchild)
if __name__ == "__main__":
tree = BinaryTree()
tree.add(0)
tree.add(1)
tree.add(2)
tree.add(3)
tree.add(4)
tree.add(5)
tree.add(6)
tree.add(7)
tree.add(8)
tree.add(9)
tree.breadth_travle()
print(" ")
tree.preorder(tree.root)
運作結果
0 1 2 3 4 5 6 7 8 9
0 1 3 7 8 4 9 2 5 6
第一個是廣度周遊順序,第二行是先序周遊結果。
中序周遊代碼
上面知道了先序周遊,那麼中序周遊就簡單了,調整以下這行列印順序就行。
# coding:utf-8
class Node(object):
"""節點"""
def __init__(self, itme):
self.ele = itme
self.lchild = None
self.rchild = None
class BinaryTree(object):
"""二叉樹"""
def __init__(self):
self.root = None
def add(self, item):
node = Node(item)
if self.root is None:
self.root = node
return
# 一個隊列,添加根元素
queue = [self.root]
while queue:
cur_node = queue.pop(0)
if cur_node.lchild is None:
cur_node.lchild = node
return
else:
queue.append(cur_node.lchild)
if cur_node.rchild is None:
cur_node.rchild = node
return
else:
queue.append(cur_node.rchild)
def breadth_travle(self):
"""廣度周遊"""
if self.root is None:
return
queue = [self.root]
while queue:
cur_node = queue.pop(0)
print(cur_node.ele, end=" ")
if cur_node.lchild is not None:
queue.append(cur_node.lchild)
if cur_node.rchild is not None:
queue.append(cur_node.rchild)
def preorder(self, node):
"""先序周遊,node 是根節點"""
if node is None:
return
print(node.ele, end=" ")
self.preorder(node.lchild)
self.preorder(node.rchild)
def inorder(self, node):
"""中序周遊"""
if node is None:
return
self.inorder(node.lchild)
print(node.ele, end=" ")
self.inorder(node.rchild)
if __name__ == "__main__":
tree = BinaryTree()
tree.add(0)
tree.add(1)
tree.add(2)
tree.add(3)
tree.add(4)
tree.add(5)
tree.add(6)
tree.add(7)
tree.add(8)
tree.add(9)
tree.breadth_travle()
print(" ")
tree.preorder(tree.root)
print(" ")
tree.inorder(tree.root)
運作結果
0 1 2 3 4 5 6 7 8 9
0 1 3 7 8 4 9 2 5 6
7 3 8 1 9 4 0 5 2 6
第三行是中序結果,下面直接貼出後續代碼。
# coding:utf-8
class Node(object):
"""節點"""
def __init__(self, itme):
self.ele = itme
self.lchild = None
self.rchild = None
class BinaryTree(object):
"""二叉樹"""
def __init__(self):
self.root = None
def add(self, item):
node = Node(item)
if self.root is None:
self.root = node
return
# 一個隊列,添加根元素
queue = [self.root]
while queue:
cur_node = queue.pop(0)
if cur_node.lchild is None:
cur_node.lchild = node
return
else:
queue.append(cur_node.lchild)
if cur_node.rchild is None:
cur_node.rchild = node
return
else:
queue.append(cur_node.rchild)
def breadth_travle(self):
"""廣度周遊"""
if self.root is None:
return
queue = [self.root]
while queue:
cur_node = queue.pop(0)
print(cur_node.ele, end=" ")
if cur_node.lchild is not None:
queue.append(cur_node.lchild)
if cur_node.rchild is not None:
queue.append(cur_node.rchild)
def preorder(self, node):
"""先序周遊,node 是根節點"""
if node is None:
return
print(node.ele, end=" ")
self.preorder(node.lchild)
self.preorder(node.rchild)
def inorder(self, node):
"""中序周遊"""
if node is None:
return
self.inorder(node.lchild)
print(node.ele, end=" ")
self.inorder(node.rchild)
def postorder(self, node):
"""中序周遊"""
if node is None:
return
self.postorder(node.lchild)
self.postorder(node.rchild)
print(node.ele, end=" ")
if __name__ == "__main__":
tree = BinaryTree()
tree.add(0)
tree.add(1)
tree.add(2)
tree.add(3)
tree.add(4)
tree.add(5)
tree.add(6)
tree.add(7)
tree.add(8)
tree.add(9)
tree.breadth_travle()
print(" ")
tree.preorder(tree.root)
print(" ")
tree.inorder(tree.root)
print(" ")
tree.postorder(tree.root)
運作結果
0 1 2 3 4 5 6 7 8 9
0 1 3 7 8 4 9 2 5 6
7 3 8 1 9 4 0 5 2 6
7 8 3 9 4 1 5 6 2 0