面试题7:重建二叉树

这篇博客探讨了如何利用二叉树的前序遍历和中序遍历结果来重建二叉树。通过分析给定的示例,解释了如何找到根节点及其左右子树的递归方法。代码实现采用Python,展示了如何通过递归构建二叉树节点,并提供了非递归前序遍历的辅助函数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:输入某二叉树的前序遍历和中序遍历的结果,请重建该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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值