题目:输入某二叉树的前序遍历和中序遍历的结果,请重建该E叉树。
假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如,输入
前序遍历序列{1,2,4, 7,3, 5, 6, 8}和中序遍历序列{4, 7,2,1,5,3,8, 6},则
,重建如图2.6所示的二叉树并输出它的头节点。
在二叉树的前序遍历序列中,第一个数字总是树的根节点的值。但在
中序遍历序列中,根节点的值在序列的中间,左子树的节点的值位于根节
点的值的左边,而右子树的节点的值位于根节点的值的右边。因此我们需
要扫描中序遍历序列,才能找到根节点的值。
如图2.7所示,前序遍历序列的第一个数字1就是根节点的值。扫描中
序遍历序列,就能确定根节点的值的位置。根据中序遍历的特点,在根节
点的值1前面的3个数字都是左子树节点的值,位于1后面的数字都是右
子树节点的值。
由于在中序遍历序列中,有3个数字是左子树节点的值,因此左子
树共有3个左子节点。同样,在前序遍历序列中,根节点后面的3个数字
就是3个左子树节点的值,再后面的所有数字都是右子树节点的值。这样
我们就在前序遍历和中序遍历两个序列中分别找到了左、右子树对应的子
序列。
既然我们已经分别找到了左、右子树的前序遍历序列和中序遍历序列,
我们可以用同样的方法分别构建左、右子树。也就是说,接下来的事情可
以用递归的方法去完成。
在想清楚如何在前序遍历和中序遍历序列中确定左、右子树的子序列
之后,我们可以写出如下的递归代码:
# 面试题7 重建二叉树
'''
这道面试题采用了递归的方法,用python写只需要几行即可。
书上的大部分代码都是在检查边界条件,显得有些复杂。
这里参考了https://github.com/Jack-Lee-Hiter/AlgorithmsByPython/blob/master/Target%20Offer/%E9%87%8D%E5%BB%BA%E4%BA%8C%E5%8F%89%E6%A0%91.py
'''
class BinaryTreeNode:
def __init__(self,data=None,left=None,right=None):
self.data = data
self.left = left
self.right = right
# 非递归前序遍历
# 当p非空或stack非空时,输出p.data并将p压入stack,遍历左子树
# 当无左子树时,弹出stack,遍历该节点的右子树
def preOrder1(BinaryTreeNode):
if BinaryTreeNode ==None:
return
stack =[]
p = BinaryTreeNode
while p!=None or stack:
while p !=None:
print(p.data,end=' ')
stack.append(p)
p = p.left
if stack:
p = stack.pop().right
print()
def ConstructCore(preorder,inorder):
if not preorder or not inorder:
return None
root = BinaryTreeNode(preorder[0])
if set(preorder) != set(inorder):
return None
i = inorder.index(root.data)
root.left = ConstructCore(preorder[1:i+1],inorder[:i])
root.right = ConstructCore(preorder[i+1:],inorder[i+1:])
return root
if __name__ == '__main__':
preorder = [1,2,4,7,3,5,6,8]
inorder = [4,7,2,1,5,3,8,6]
re_root = ConstructCore(preorder,inorder)
preOrder1(re_root)