題目描述:
輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建二叉樹並返回。
什麼是二叉樹?
二叉樹(Binary Tree)是n(n≥0)個節點的有限集合,它或者是空集(n=0),或者是由一個根節點以及兩棵互不相交的、分別稱爲左子樹和右子樹的二叉樹組成。二叉樹與普通有序樹不同,二叉樹嚴格區分左孩子和右孩子,即使只有一個子節點也要區分左右。
二叉樹的遍歷
遍歷 :沿某條搜索路徑周遊二叉樹,對樹中的每一個節點訪問一次且僅訪問一次。
遇到沒遍歷的新節點都當根處理
先序遍歷: 先訪問樹根,再訪問左子樹,最後訪問右子樹;根左右
中序遍歷: 先訪問左子樹,再訪問樹根,最後訪問右子樹;左根右
後序遍歷: 先訪問左子樹,再訪問右子樹,最後訪問樹根;左右根
層次遍歷: 從根節點開始,逐層從左向右進行遍歷。
使用Python實現二叉樹
# 二叉樹節點
class TreeNode:
def __init__(self, val=None, left=None, right=None):
self.val = val
self.left = left
self.right = right
# 二叉樹操作
class Bitree:
def __init__(self, root=None):
self.root = root # 獲取樹根
# 先序遍歷
def preOrder(self,node):
# 傳入根節點
if node is None:
return
# 打印根節點數據
print(node.val,end=' ')
# 將根節點的左點節 作爲根節點 遞歸調用自身,直至滿足node is None,停止遞歸
self.preOrder(node.left)
self.preOrder(node.right)
# 中序遍歷
def inOrder(self, node):
if node is None:
return
self.inOrder(node.left)
print(node.val, end=' ')
self.inOrder(node.right)
# 後序遍歷
def postOrder(self, node):
if node is None:
return
self.postOrder(node.left)
self.postOrder(node.right)
print(node.val, end=' ')
if __name__ == "__main__":
# 後序遍歷 BFGDIHECA
# 構建樹
b = TreeNode('B')
f = TreeNode('F')
g = TreeNode('G')
d = TreeNode('D', f, g)
i = TreeNode('I')
h = TreeNode('H')
e = TreeNode('E', i, h)
c = TreeNode('C', d, e)
a = TreeNode('A', b, c) # 樹根
# 初始化樹對象,得到樹根
bt = Bitree(a)
# 先序
bt.preOrder(bt.root)
print()
# 中序
bt.inOrder(bt.root)
print()
# 後序
bt.postOrder(bt.root)
print()
根據題目構建二叉樹圖
構建代碼
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
class Solution:
# 返回構造的TreeNode根節點
def reConstructBinaryTree(self, pre: list, tin: list) -> object:
"""
pre: 前序列表
tin: 中序列表
"""
# write code here
if len(pre) == 0:
return None
if len(pre) == 1:
return TreeNode(pre[0])
else:
root = TreeNode(pre[0]) # 前序序列的第一個肯定是當前子樹的根節點
rootid = tin.index(root.val) # 通過根節點在中序序列中的位置劃分出左右子樹包含的節點
root.left = self.reConstructBinaryTree(pre[1:rootid + 1], tin[:rootid])
root.right = self.reConstructBinaryTree(pre[rootid + 1:], tin[rootid + 1:])
return root
代碼流程
對結果進行驗證
完整代碼
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
class Solution:
# 返回構造的TreeNode根節點
def reConstructBinaryTree(self, pre: list, tin: list) -> object:
"""
pre: 前序列表
tin: 中序列表
"""
# write code here
if len(pre) == 0:
return None
if len(pre) == 1:
return TreeNode(pre[0])
else:
root = TreeNode(pre[0]) # 前序序列的第一個肯定是當前子樹的根節點
rootid = tin.index(root.val) # 通過根節點在中序序列中的位置劃分出左右子樹包含的節點
root.left = self.reConstructBinaryTree(pre[1:rootid + 1], tin[:rootid])
root.right = self.reConstructBinaryTree(pre[rootid + 1:], tin[rootid + 1:])
return root
class Bitree:
def __init__(self, root=None):
self.root = root # 獲取樹根
# 先序遍歷
def preOrder(self, node):
# 傳入根節點
if node is None:
return
# 打印根節點數據
print(node.val, end=' ')
# 將根節點的做點節 作爲根節點 調用自身
self.preOrder(node.left)
self.preOrder(node.right)
# 中序遍歷
def inOrder(self, node):
if node is None:
return
self.inOrder(node.left)
print(node.val, end=' ')
self.inOrder(node.right)
# 後序遍歷
def postOrder(self, node):
if node is None:
return
self.postOrder(node.left)
self.postOrder(node.right)
print(node.val, end=' ')
if __name__ == '__main__':
s = Solution()
pre = [1, 2, 4, 7, 3, 5, 6, 8]
tin = [4, 7, 2, 1, 5, 3, 8, 6]
root = s.reConstructBinaryTree(pre, tin)
# 初始化樹對象,得到樹根
bt = Bitree(root)
# 先序
bt.preOrder(bt.root) # 1 2 4 7 3 5 6 8
print()
# 中序
bt.inOrder(bt.root) # 4 7 2 1 5 3 8 6
print()
# 後序
bt.postOrder(bt.root) # 7 4 2 5 8 6 3 1
print()
補充 代碼實現二叉樹層次遍歷
'''
利用隊列先進先出特性,實現二叉樹層次遍歷
'''
# 自定義隊列異常
class QueueError(Exception):
pass
# 隊列操作類
class SQueue:
def __init__(self):
self._elems = []
# 判斷隊列空
def is_empty(self):
return self._elems == []
# 入隊 從列表尾部
def enqueue(self, elem):
self._elems.append(elem)
# 出隊 從列表開頭
def dequeue(self):
if not self._elems:
raise QueueError("Queue is empty")
return self._elems.pop(0)
# 二叉樹節點
class TreeNode:
def __init__(self, val=None, left=None, right=None):
self.val = val
self.left = left
self.right = right
class Bitree:
def __init__(self, root=None):
self.root = root # 獲取樹根
# 層次遍歷
def levelOrder(self,node):
sq = SQueue()
sq.enqueue(node) # 從node遍歷
while not sq.is_empty():
node = sq.dequeue() # 出隊一個
print(node.val,end=' ') # 遍歷數據
if node.left:
sq.enqueue(node.left)
if node.right:
sq.enqueue(node.right)
如有錯誤,歡迎指正