从前序与中序遍历序列构造二叉树(C++实现)

简介: 从前序与中序遍历序列构造二叉树(C++实现)


题目

思路分析

  • 我们可以通过递归实现的二叉树构建函数。它根据给定的先序遍历序列和中序遍历序列构建一棵二叉树,并返回根节点
  • 可以创建一个_build 函数,该函数负责构建二叉树的节点,通过分割先序遍历序列和中序遍历序列,并递归构建左子树和右子树来完成整个二叉树的构建过程。
  • 最终,buildTree 函数调用 _build 函数,并返回构建的二叉树的根节点。

代码

class Solution {
public:
    TreeNode* _build(vector<int>& preorder, vector<int>& inorder, int& peri, int begin, int end) 
    {
         // 如果开始索引大于结束索引,则返回空指针,表示当前子树为空
         if (begin > end) {
             return nullptr;
         }
         int rooti = 0;
         // 在中序遍历序列中找到当前根节点的索引
         while (rooti <= end) {
             if (inorder[rooti] == preorder[peri]) {
                 break;
             }
             rooti++;
         }
         // 创建当前根节点
         TreeNode* root = new TreeNode(preorder[peri++]);
         // 构建左子树
         // 左子树的先序遍历序列为 [begin, rooti-1]
         // 左子树的中序遍历序列为 [begin, rooti-1]
         root->left = _build(preorder, inorder, peri, begin, rooti-1);
         // 构建右子树
         // 右子树的先序遍历序列为 [rooti+1, end]
         // 右子树的中序遍历序列为 [rooti+1, end]
         root->right = _build(preorder, inorder, peri, rooti+1, end);
         return root;
    }
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) 
    {
        int i = 0;
        // 调用内部函数 _build 构建二叉树
        // 初始时 peri 为 0,表示从先序遍历序列的第一个元素开始构建
        // 根据先序遍历序列和中序遍历序列构建二叉树,并返回根节点
        TreeNode* root = _build(preorder, inorder, i, 0, preorder.size()-1);
        return root;
    }
};

代码讲解

首先判断起始索引 begin 是否大于结束索引 end,如果是,则说明当前子树为空,返回空指针。

在中序遍历序列 inorder 中找到当前根节点的索引 rooti,该索引表示根节点在中序遍历中的位置。在循环中,不断遍历中序遍历序列,直到找到与先序遍历序列 preorder[peri] 相等的值。找到后,rooti 就是根节点的索引。

创建当前根节点,节点的值为 preorder[peri]。

根据先序遍历序列和中序遍历序列的特性,可以将当前子树分为左子树和右子树。左子树的先序遍历序列为 preorder[begin, rooti-1],左子树的中序遍历序列为 inorder[begin, rooti-1]。右子树的先序遍历序列为 preorder[rooti+1, end],右子树的中序遍历序列为 inorder[rooti+1, end]。

递归调用 _build 函数,分别构建左子树和右子树,并将返回的根节点设置为当前根节点的左孩子和右孩子。

返回当前根节点。


总结:

在 buildTree 函数中,首先定义了一个变量 i,初始值为 0,作为 _build 函数中 peri 的初始值。然后调用 _build 函数,传入先序遍历序列 preorder、中序遍历序列 inorder、i、0 和 preorder.size()-1,即整个序列的起始和结束索引。最后返回构建的二叉树的根节点。

相关文章
|
1月前
|
C++
基本二叉树与排序二叉树(C++源码)
本程序实现二叉树基本操作与二叉排序树应用。支持前序建树、四种遍历、求深度、叶子数、第K层节点数及查找功能;并实现二叉排序树的构建、中序输出与查找比较次数统计,分析不同插入顺序对树形态和查找效率的影响。
|
10月前
|
Java C++
【C++数据结构——树】二叉树的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现二叉树的基本运算。​ 相关知识 创建二叉树 销毁二叉树 查找结点 求二叉树的高度 输出二叉树 //二叉树节点结构体定义 structTreeNode{ intval; TreeNode*left; TreeNode*right; TreeNode(intx):val(x),left(NULL),right(NULL){} }; 创建二叉树 //创建二叉树函数(简单示例,手动构建) TreeNode*create
297 12
|
10月前
|
C++
【C++数据结构——树】二叉树的性质(头歌实践教学平台习题)【合集】
本文档介绍了如何根据二叉树的括号表示串创建二叉树,并计算其结点个数、叶子结点个数、某结点的层次和二叉树的宽度。主要内容包括: 1. **定义二叉树节点结构体**:定义了包含节点值、左子节点指针和右子节点指针的结构体。 2. **实现构建二叉树的函数**:通过解析括号表示串,递归地构建二叉树的各个节点及其子树。 3. **使用示例**:展示了如何调用 `buildTree` 函数构建二叉树并进行简单验证。 4. **计算二叉树属性**: - 计算二叉树节点个数。 - 计算二叉树叶子节点个数。 - 计算某节点的层次。 - 计算二叉树的宽度。 最后,提供了测试说明及通关代
191 10
|
10月前
|
存储 算法 测试技术
【C++数据结构——树】二叉树的遍历算法(头歌教学实验平台习题) 【合集】
本任务旨在实现二叉树的遍历,包括先序、中序、后序和层次遍历。首先介绍了二叉树的基本概念与结构定义,并通过C++代码示例展示了如何定义二叉树节点及构建二叉树。接着详细讲解了四种遍历方法的递归实现逻辑,以及层次遍历中队列的应用。最后提供了测试用例和预期输出,确保代码正确性。通过这些内容,帮助读者理解并掌握二叉树遍历的核心思想与实现技巧。
440 3
|
10月前
|
数据采集 存储 算法
【C++数据结构——图】图的遍历(头歌教学实验平台习题) 【合集】
本文介绍了图的遍历算法,包括深度优先遍历(DFS)和广度优先遍历(BFS)。深度优先遍历通过递归方式从起始节点深入探索图,适用于寻找路径、拓扑排序等场景;广度优先遍历则按层次逐层访问节点,适合无权图最短路径和网络爬虫等应用。文中提供了C++代码示例,演示了如何实现这两种遍历方法,并附有测试用例及结果,帮助读者理解和实践图的遍历算法。
514 0
|
JavaScript 前端开发 Java
面向对象编程(C++篇2)——构造
面向对象编程(C++篇2)——构造
75 0
|
9月前
|
编译器 C++ 开发者
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。
|
5月前
|
人工智能 机器人 编译器
c++模板初阶----函数模板与类模板
class 类模板名private://类内成员声明class Apublic:A(T val):a(val){}private:T a;return 0;运行结果:注意:类模板中的成员函数若是放在类外定义时,需要加模板参数列表。return 0;
158 0
|
5月前
|
存储 编译器 程序员
c++的类(附含explicit关键字,友元,内部类)
本文介绍了C++中类的核心概念与用法,涵盖封装、继承、多态三大特性。重点讲解了类的定义(`class`与`struct`)、访问限定符(`private`、`public`、`protected`)、类的作用域及成员函数的声明与定义分离。同时深入探讨了类的大小计算、`this`指针、默认成员函数(构造函数、析构函数、拷贝构造、赋值重载)以及运算符重载等内容。 文章还详细分析了`explicit`关键字的作用、静态成员(变量与函数)、友元(友元函数与友元类)的概念及其使用场景,并简要介绍了内部类的特性。
249 0
|
7月前
|
编译器 C++ 容器
【c++11】c++11新特性(上)(列表初始化、右值引用和移动语义、类的新默认成员函数、lambda表达式)
C++11为C++带来了革命性变化,引入了列表初始化、右值引用、移动语义、类的新默认成员函数和lambda表达式等特性。列表初始化统一了对象初始化方式,initializer_list简化了容器多元素初始化;右值引用和移动语义优化了资源管理,减少拷贝开销;类新增移动构造和移动赋值函数提升性能;lambda表达式提供匿名函数对象,增强代码简洁性和灵活性。这些特性共同推动了现代C++编程的发展,提升了开发效率与程序性能。
292 12