根據樹前序遍歷和中序遍歷構建二叉樹
問題:已知一個二叉樹前序遍歷為:ABDEGCFH,中序遍歷為:DBGEACHF,則該二叉樹的后序遍歷為?
思路是這樣的:1:根據前序遍歷來確定每次根節點的位置,因為前序遍歷先訪問的是根節點,所以前序遍歷第一個位置就是根節點。 2:根據根節點和中序遍歷將樹划分為左右兩棵樹。3:根據第一步和第二步遞歸的處理左右兩棵樹。
第一步:根據前序遍歷 A B D E G C F H 確定頭結點是A,根據中序遍歷 D B G E A C H F 將樹划分為左子樹 D B G E 和右子樹 C H F。
第二步:划分為左右兩棵子樹:對於左子樹,前序遍歷是 B D E G,后續遍歷是 D B G E。對於右子樹,前序遍歷是 C F H,后續遍歷是 C H F。
第三步:對左子樹和右子樹分別運用第一步和第二步進行分析。
遞歸結束的條件:當中序遍歷的節點只剩下一個節點的時候,那么這個節點就是葉子節點。
整體的操作流程如下:
Python代碼如下:
class TreeNode:
"""樹節點"""
def __init__(self, x):
self.val = x
self.left = None
self.right = None
class Solution:
def reConstructBinaryTree(self, pre, tin):
"""根據前序遍歷和中序遍歷來重建一顆二叉樹,要求前序遍歷和中序遍歷當中字符不重復
Args:
pre: 前序遍歷 list類型或者者str類型
tin: 中序遍歷
Returns:
head: 一個TreeNode類型的根節點
"""
return self.rebuild_tree(pre, 0, len(pre)-1, tin, 0, len(tin)-1)
def rebuild_tree(self, pre, pre_start, pre_end, tin, tin_start, tin_end):
"""遞歸的進行樹的重建"""
if pre_start > pre_end or tin_start > tin_end:
return None
head = TreeNode(pre[pre_start])
tin_mid = tin.index(pre[pre_start])
left_length = tin_mid - tin_start
head.left = self.rebuild_tree(pre, pre_start+1, pre_start+left_length,
tin, tin_start, tin_mid-1)
head.right = self.rebuild_tree(pre,pre_start+left_length+1, pre_end,
tin, tin_mid+1, tin_end)
return head
def post_order_print(head):
"""以后序遍歷的方式打印一顆二叉樹"""
if head is None:
return
post_order_print(head.left)
post_order_print(head.right)
print(head.val,end='')
if __name__ == '__main__':
pre = 'ABDEGCFH'
tin = 'DBGEACHF'
s = Solution()
head = s.reConstructBinaryTree(pre, tin)
post_order_print(head) # result: DGEBHFCA
根據樹后序遍歷和中序遍歷構建二叉樹
道理是一樣的,根據后序遍歷來確定根節點的位置,由於后序遍歷最后訪問根節點, 所以此時最后一個節點就是根節點。根據中序遍歷來划分左右子樹,然后迭代求解。
根據樹前序遍歷和后序遍歷不能構建唯一的二叉樹
前序和后序在本質上都是將父節點與子結點進行分離,但並沒有指明左子樹和右子樹的能力,因此得到這兩個序列只能明確父子關系,而不能確定一個二叉樹。
比如前序遍歷為ABC,后續遍歷為CBA,可以構造出下面兩棵樹,可以發現這並不唯一: