AcWing 18. 重建二叉树

本文介绍了一种通过前序遍历和中序遍历结果来重建二叉树的方法。利用递归算法,根据先序和中序遍历的特点,确定根节点,并划分左右子树,最终完成整棵树的构建。

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

题目描述

输入一棵二叉树前序遍历和中序遍历的结果,请重建该二叉树。

注意:

  • 二叉树中每个节点的值都互不相同;
  • 输入的前序遍历和中序遍历一定合法;

样例

给定:
前序遍历是:[3, 9, 20, 15, 7]
中序遍历是:[9, 3, 15, 20, 7]

返回:[3, 9, 20, null, null, 15, 7, null, null, null, null]
返回的二叉树如下所示:
    3
   / \
  9  20
    /  \
   15   7

 算法

(递归) O(n)

首先应该注意,先序遍历的第一个数就是根节点的值;
然后在中序遍历中找到根节点值对应的位置 pos,则 pos 左边是左子树的中序遍历,右边是右子树的中序遍历;
根据先序遍历和中序遍历的特性,可知:

当前根节点在中序遍历中的位置是pos,如图得,先序遍历中左子树为[1,pos+1),右子树为[pos+1,最后],中序遍历中左子树为[0,pos),右子树为[pos+1,最后]

有了左右子树的前序遍历和中序遍历,我们的思路就是先递归创建出左右子树,然后再创建根节点。

Python3 代码

### Python3 代码
# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution(object):
    def buildTree(self, preorder, inorder):
        """
        :type preorder: List[int]
        :type inorder: List[int]
        :rtype: TreeNode
        """
        # 若先序遍历为空,即二叉树为空,则返回None
        if len(preorder) == 0:
            return None
        # 若二叉树只有一个根节点,直接返回这个根节点
        if len(preorder) == 1:
            return TreeNode(preorder[0])
        root = TreeNode(preorder[0])
        # list.index(value) 从列表list中找出某个值value第一个匹配项的索引位置,如果没有找到对象则抛出异常。
        pos = inorder.index(preorder[0])
        root.left = self.buildTree(preorder[1:pos+1], inorder[:pos])
        root.right = self.buildTree(preorder[pos+1:], inorder[pos+1:])
        return root
        

 

### 线索二叉树的结构类型及其分类 #### 定义与背景 线索二叉树是在传统二叉树的基础上增加了一些额外的信息来提高遍历效率的数据结构。这种增强主要体现在通过引入所谓的“线索”(指向、中或后前驱/后继节点的指针),使得无需栈或其他辅助空间即可实现高效的遍历操作[^1]。 #### 数据结构中的分类 从理论上讲,二叉树本身作为一种抽象模型代表的是逻辑结构——更精确地说是非线性的逻辑结构之一[^2]。然而,一旦我们对二叉树进行了具体的实现并加入了诸如线索这样的附加成分时,就涉及到了如何在内存或者磁盘等实际介质上组织这些数据的问题,这就进入了物理层面或者说存储结构领域[^3]。 具体来说: - **逻辑结构角度**:无论是否添加了线索,二叉树本质上仍然保持其原有的父子关系模式不变,因此依旧归类于非线性逻辑结构。 - **物理结构角度**:由于线索的存在依赖特定技术手段表达(比如C语言里的指针机制),而且直接影响到该结构在硬件资源上的布局方式,故而可以视作一种特殊的物理结构形式[^1]。 总结而言,虽然线索二叉树保留了原有二叉树作为非线性逻辑结构的本质属性,但由于增加了用于优化访问路径的新要素—即所谓‘线索’,使其成为了兼具独特特性和功能扩展意义下的物理表现形态。 ```c typedef int ThreadedBinaryTreeDataType; typedef struct ThreadedBinaryTree { ThreadedBinaryTreeDataType _data; struct ThreadedBinaryTree* _left; struct ThreadedBinaryTree* _right; int _LeftFlag, _RightFlag; // 左右标志位:0 表示正常子节点指针,1 表示线索指针 } TBT, *pTBT; // 创建一个简单的线索化函数框架 (仅示意用途) void InOrderThreading(pTBT root){ static pTBT pre = NULL;// 记录当前节点的前驱 if(root != NULL){ InOrderThreading(root->_left); if(root->_left == NULL){ root->_left = pre; root->_LeftFlag = 1; } if(pre && pre->_right == NULL){ pre->_right = root; pre->_RightFlag = 1; } pre = root; InOrderThreading(root->_right); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值