重建二叉树[C++版]

问题描述

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。
假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
例如,输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

解决思想

首先我们看一下C++版本的树结构是如何实现的。

 struct TreeNode {
   
 	int val;
 	TreeNode *left;
 	TreeNode *right;
 	TreeNode(int x) : val(x), left(NULL), right(NULL) {
   }
 };

这里使用了一个结构体来进行实现,包含三个成员,分别是当前节点的值,左子树和右子树。值得一提的是,这里还实现了一个有参构造函数,分别用一个int类型的变量来初始化节点的值和NULL来初始化左右两个子树(指针)。

思想1:树的性质

二叉树的遍历方式:层序遍历,前序遍历,中序遍历,后序遍历。
通俗来讲,前序遍历、中序遍历和后序遍历的主要区别是遍历顺序,可以简单的理解为前序遍历(根左右),中序遍历(左根右)和后序遍历(左右根)
以上述输入为例进行分析:
前序:[1, 2, 4, 7, 3, 5, 6, 8]
中序:[4, 7, 2, 1, 5, 3, 8, 6]
我们先人为的去进行判断。根据前序遍历的方式(根左右),我们可以得到前序遍历结果的第一个元素就是整个二叉树的根节点,所以我们记录root_value = 1。由于二叉树的每一个节点都是互斥的,根据中序遍历的方式(左根右),我们只要在中序遍历的结果中发现了根节点,是不是就可以区分开左右子树了呢
左子树中的节点值分别为[4, 7, 2],而右子树为[5, 3, 8, 6],注意,这里和顺序无关,只是简单的区分组成
左子树长度为3,右子树长度为4。由于我们已经有了整棵二叉树的前序遍历和中序遍历结果,我们可以得到:
左子树的前序及中序遍历结果,右子树的前序及中序遍历结果
左子树的前序遍历结果:[2, 4, 7]。中序遍历结果:[4, 7, 2]。
右子树的前序遍历结果:[3, 5, 6, 8]。中序遍历结果:[5, 3, 8, 6]。
咋得到的?左子树的前序遍历就是整个子树前序遍历的一部分吧,1是根节点,所以去掉。此时整个二叉树前序遍历变为[2, 4, 7, 3, 5, 6, 8]。由于中序遍历结果划分了左子树和右子树,我们可以知道左子树的长度吧?看中序遍历中1前面有几个数呗,有3个。所以得到了左子树的前序遍历结果:[2, 4, 7]。那么右子树的呢?剩下的[3, 5, 6, 8]不就是了?
下面简单说明了整个过程。
在这里插入图片描述

思想2:递归

有了左子树和右子树的前序遍历和中序遍历结果,我们只要递归地执行上述操作即可。
递归出口:当两个遍历结果输入的长度为空时。

我的代码

#include <iostream>
#include <vector>
using namespace std;

// 结构体定义树的类型
struct TreeNode {
   
    int val;
    TreeNode *left;
    
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值