首页 > 其他分享 >中序和后序构造二叉树

中序和后序构造二叉树

时间:2025-01-08 21:34:39浏览次数:3  
标签:遍历 后序 中序 二叉树 inorder 节点 postorder

中序和后序构造二叉树

给定二叉树的中序遍历和后序遍历序列,请构造出该二叉树并返回根节点。中序遍历的顺序是左子树->根节点 ->右子树;后序遍历的顺序是左子树->右子树->根节点

输入格式

·一个整数数组 inorder,表示中序遍历的结果

·一个整数数组 postorder,表示后序遍历的结果

输出格式

返回构造出的二叉树的根节点

输入样例

inorder = [9, 3, 15, 20, 7]
postorder = [9, 15, 7, 20, 3]

输出样例

[3, 9, 20, null, null, 15, 7]

二叉树结构

    3
   / \
  9  20
     / \
    15  7

题目要求根据中序遍历和后序遍历构造二叉树,这实际上是经典的重建二叉树问题。我们可以利用中序遍历和后序遍历的特性来逐步确定各个子树的根节点、左子树和右子树,从而构建整个树结构。具体方法如下:

  1. 从后序遍历的最后一个元素开始,这是树的根节点。

  2. 在中序遍历中找到这个根节点的位置,这样就可以将中序遍历分为左子树和右子树。

  3. 回到后序遍历中相应地划分出左子树和右子树的部分,递归地构造子树。

  4. 重复步骤1到3,直到完成树的构建。

java代码

// Definition for a binary tree node.
class TreeNode {
    int val; // 节点的值
    TreeNode left; // 左子节点
    TreeNode right; // 右子节点

    // 构造函数,初始化节点值
    TreeNode(int x) { 
        val = x; 
    }
}

public class Solution {
    /**
     * 根据中序遍历和后序遍历的数组构造二叉树
     *
     * @param inorder   中序遍历数组
     * @param postorder 后序遍历数组
     * @return 构造的二叉树的根节点
     */
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        // 如果输入数组为 null,或者两者长度不相等,则无法构造树,返回 null
        if (inorder == null || postorder == null || inorder.length != postorder.length) {
            return null;
        }
        // 调用辅助方法构建二叉树
        return buildTreeHelper(inorder, 0, inorder.length - 1, postorder, 0, postorder.length - 1);
    }

    /**
     * 递归辅助函数,用于构造二叉树
     *
     * @param inorder    中序遍历数组
     * @param inStart    当前中序数组的起始索引
     * @param inEnd      当前中序数组的结束索引
     * @param postorder  后序遍历数组
     * @param postStart  当前后序数组的起始索引
     * @param postEnd    当前后序数组的结束索引
     * @return 构造的子树的根节点
     */
    private TreeNode buildTreeHelper(int[] inorder, int inStart, int inEnd, int[] postorder, int postStart, int postEnd) {
        // 递归终止条件:中序或后序数组范围无效时返回 null
        if (inStart > inEnd || postStart > postEnd) {
            return null;
        }

        // 从后序数组的最后一个元素获取当前子树的根节点值
        int rootVal = postorder[postEnd];
        // 创建根节点
        TreeNode root = new TreeNode(rootVal);

        // 在中序数组中找到根节点的索引,用于划分左右子树
        int rootIndex = inStart;
        for (int i = inStart; i <= inEnd; i++) {
            if (inorder[i] == rootVal) {
                rootIndex = i;
                break;
            }
        }

        // 计算左子树的节点数量
        int leftSize = rootIndex - inStart;

        // 构造左子树,更新中序和后序数组的范围
        root.left = buildTreeHelper(inorder, inStart, rootIndex - 1, postorder, postStart, postStart + leftSize - 1);
        // 构造右子树,更新中序和后序数组的范围
        root.right = buildTreeHelper(inorder, rootIndex + 1, inEnd, postorder, postStart + leftSize, postEnd - 1);

        // 返回当前子树的根节点
        return root;
    }
}

C++代码

#include <vector>

using namespace std;

// 定义二叉树节点结构
struct TreeNode {
    int val;                 // 节点值
    TreeNode *left;          // 左子节点指针
    TreeNode *right;         // 右子节点指针

    // 构造函数,用于初始化节点值并将子节点设置为 nullptr
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};

class Solution {
public:
    /**
     * 根据中序遍历和后序遍历的结果构建二叉树
     * @param inorder 中序遍历数组
     * @param postorder 后序遍历数组
     * @return 构造的二叉树的根节点
     */
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        // 调用辅助函数递归构造二叉树
        return buildTreeHelper(inorder, 0, inorder.size() - 1, postorder, 0, postorder.size() - 1);
    }

private:
    /**
     * 递归辅助函数,用于分区构建子树
     * @param inorder 中序遍历数组
     * @param inStart 当前子树中序遍历起始索引
     * @param inEnd 当前子树中序遍历结束索引
     * @param postorder 后序遍历数组
     * @param postStart 当前子树后序遍历起始索引
     * @param postEnd 当前子树后序遍历结束索引
     * @return 当前子树的根节点
     */
    TreeNode* buildTreeHelper(vector<int>& inorder, int inStart, int inEnd, vector<int>& postorder, int postStart, int postEnd) {
        // 递归终止条件:当索引范围无效时返回 nullptr
        if (inStart > inEnd || postStart > postEnd) {
            return nullptr;
        }

        // 后序遍历的最后一个元素是当前子树的根节点值
        int rootVal = postorder[postEnd];
        // 创建根节点
        TreeNode* root = new TreeNode(rootVal);

        // 在中序遍历数组中找到根节点的位置,以划分左右子树
        int rootIndex = inStart;
        for (int i = inStart; i <= inEnd; i++) {
            if (inorder[i] == rootVal) {
                rootIndex = i;
                break;
            }
        }

        // 计算左子树的节点数量
        int leftSize = rootIndex - inStart;

        // 递归构造左子树
        root->left = buildTreeHelper(inorder, inStart, rootIndex - 1, postorder, postStart, postStart + leftSize - 1);
        // 递归构造右子树
        root->right = buildTreeHelper(inorder, rootIndex + 1, inEnd, postorder, postStart + leftSize, postEnd - 1);

        // 返回当前子树的根节点
        return root;
    }
};

python代码

# 定义二叉树节点类
class TreeNode:
    def __init__(self, x):
        self.val = x       # 节点的值
        self.left = None   # 左子节点指针
        self.right = None  # 右子节点指针

class Solution:
    """
    根据中序遍历和后序遍历数组构造二叉树
    """
    def buildTree(self, inorder: list[int], postorder: list[int]) -> TreeNode:
        # 如果输入数组为空或长度不一致,无法构造树,返回 None
        if not inorder or not postorder or len(inorder) != len(postorder):
            return None
        
        # 调用辅助函数递归构建二叉树
        return self.buildTreeHelper(inorder, 0, len(inorder) - 1, postorder, 0, len(postorder) - 1)
    
    def buildTreeHelper(self, inorder, inStart, inEnd, postorder, postStart, postEnd):
        """
        递归辅助函数,用于分区构建二叉树
        :param inorder: 中序遍历数组
        :param inStart: 当前中序遍历数组的起始索引
        :param inEnd: 当前中序遍历数组的结束索引
        :param postorder: 后序遍历数组
        :param postStart: 当前后序遍历数组的起始索引
        :param postEnd: 当前后序遍历数组的结束索引
        :return: 构造的二叉树的根节点
        """
        # 递归终止条件:索引范围无效时返回 None
        if inStart > inEnd or postStart > postEnd:
            return None

        # 后序遍历的最后一个元素是当前子树的根节点值
        rootVal = postorder[postEnd]
        # 创建根节点
        root = TreeNode(rootVal)

        # 在中序遍历数组中找到根节点的位置,用于划分左右子树
        rootIndex = inStart
        for i in range(inStart, inEnd + 1):
            if inorder[i] == rootVal:
                rootIndex = i
                break

        # 左子树的节点数量
        leftSize = rootIndex - inStart

        # 递归构造左子树
        root.left = self.buildTreeHelper(
            inorder, inStart, rootIndex - 1, 
            postorder, postStart, postStart + leftSize - 1
        )
        # 递归构造右子树
        root.right = self.buildTreeHelper(
            inorder, rootIndex + 1, inEnd, 
            postorder, postStart + leftSize, postEnd - 1
        )

        # 返回当前子树的根节点
        return root

标签:遍历,后序,中序,二叉树,inorder,节点,postorder
From: https://blog.csdn.net/weixin_46545179/article/details/145010019

相关文章

  • 刷题记录(回顾)二叉树-2,3,4,5 二叉树的各种遍历
    二叉树共有两类遍历方式(理解前中后序+层序)DFS:深度优先搜索:即前中后三序遍历所谓前中后序就是:“左”,“中”,“右”这三个元素组成的排列中“中”的位置,中代表处理节点,左代表访问左孩子右代表访问右孩子    前序遍历:中左右,先处理节点后访问左右孩子    中......
  • 数据结构与算法之二叉树: LeetCode 107. 二叉树的层序遍历 II (Ts版)
    二叉树的层序遍历IIhttps://leetcode.cn/problems/binary-tree-level-order-traversal-ii/description/描述给你二叉树的根节点root,返回其节点值自底向上的层序遍历。(即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)示例1输入:root=[3,9,20,null,nul......
  • Spark 源码分析(一) SparkRpc中序列化与反序列化Serializer的抽象类解读 (正在更新中~)
    接上一章请先看解读序列化抽象类第一部分目录接上一章请先看解读序列化抽象类第一部分2.Java序列化实现类JavaSerializer(1)JavaSerializationStream类定义了一个java序列化流继承了SerializationStream抽象类代码实际例子1:序列化(2)JavaDeserializationStream......
  • 代码随想录:二叉树的递归遍历
    代码随想录:二叉树的递归遍历现在是找借口时间,一开始是期末考试太忙了,后来是过年放假,一晃这么久没写题了,这样不好。,看了一下我现在leetcode才40多道题呢定个目标,三月之前刷完代码随想录,并且把hot100的简单中等题都写了。/***Definitionforabinarytreenode.*structTre......
  • C语言数据结构与算法(二叉树)
    1.二叉树的概念及结构1.1概念一棵二叉树是结点的一个有限集合,该集合:1.或者为空2.由一个根节点加上两棵别称为左子树和右子树的二叉树组成特性:1.二叉树不存在度大于2的结点2.二叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序树1.2特殊的二叉树满二叉树:每......
  • 【Leetcode_Hot100】二叉树
    二叉树94.二叉树的中序遍历104.二叉树的最大深度226.翻转二叉树101.对称二叉树543.二叉树的直径102.二叉树的层序遍历108.将有序数组转换为二叉搜索树98.验证二叉搜索树230.二叉搜索树中第K小的元素199.二叉树的右视图114.二叉树展开为链表105.从前序与......
  • 【Day 11 LeetCode】二叉树的遍历
    一、二叉树的遍历二叉树的遍历主要分为深度优先遍历和广度优先遍历。深度优先是先往深处走,走到尽头返回;广度优先遍历是一层一层往下遍历。其中,深度优先遍历对应三种顺序,前序、中序、后序遍历,特点也很好记,就是根节点的位置。根节点位于前面就是前序,遍历顺序为根节点-左子......
  • 力扣刷题:二叉树OJ篇(下)
    大家好,这里是小编的博客频道小编的博客:就爱学编程很高兴在CSDN这个大家庭与大家相识,希望能在这里与大家共同进步,共同收获更好的自己!!!目录1.(1)题目描述(2)解题思路2.对称二叉树(1)题目描述(2)解题思路3.另一棵树的子树(1)题目描述(2)解题思路4.二叉树的构建及遍历(1)题目描述(2......
  • 算法基础 -二叉树遍历
    文章目录1.二叉树概念2.层序遍历2.1.复杂度2.2.示例12.3.示例23.层次遍历23.1.层次遍历规则3.2.层次遍历举例3.3.层次遍历代码4.先序遍历4.1.先序遍历规则4.2.先序遍历举例4.3.先序遍历代码(递归)4.4.先序遍历代码(非递归)5.中序遍历5.1.中序遍历规则5.2.......
  • python中的二叉树
    在刷算法题中,二叉树是常见的题型,掌握二叉树的基本语法和常见操作是非常重要的。以下是一些在Python中常用的二叉树语法及操作,特别是刷算法题时用到的。1.二叉树的定义:首先定义二叉树的节点结构。每个节点通常有三个属性:val(节点的值),left(左子节点),right(右子节点)。#Definitionfo......