【二叉树构建与遍历3】先序遍历+后序遍历构建一个满二叉树并输出中序遍历 C++实现

news2024/11/16 15:30:46

注意:根据先序遍历与后序遍历只有在满二叉树的情况下才能确定一个唯一的树。这里介绍的是根据先序遍历+后序遍历构建一个满二叉树并输出中序遍历顺序。

思路:

先来一个例子:

先序遍历序列为:FDXEABG

后序遍历序列为:XEDBGAF

要根据先序序列和后序序列确定这个满二叉树,通用的步骤为:

1.根据先序序列的第一位或后序序列的最后一位确定这棵树的根root,但是不能用于确定它的左子树与右子树;

2.根据后序序列的倒数第二位确定右子树的根,这里命名为rRoot,这是用于定位的,用于确定根root的左子树与右子树;

3.在先序序列中找到右子树的根rRoot所在的位置,右子树的根rRoot的左边(除首位)就是该树的左子树的节点,右子树的根rRoot以及右边就是根root的右子树的节点;

4.根据左子树节点和右子树节点在后序序列中分别找到对应的子串;

5.对4中找到的两个子串分别重复1 2 3 4步,左子树节点用于构建左子树,右子树节点用于构建右子树,直到所有的节点都用于构建这棵树。

示例:

根据以上的案例走一遍:

1.由先序遍历序列为:FDXEABG可知,树root的根节点为F;

2.在后序遍历序列XEDBGAF中找到右子树的跟,这里命名为rRoot,也就是倒数第二个节点A

3.在先序遍历序列FDXEABG找到根root的右子树的跟A的索引为4,左边DXE(除首位)就是该树的左子树的节点,根A以及右边的ABG就是根root的右子树的节点;

4.根据树的左子树节点DXE和右子树节点ABG在后序序列中分别找到对应的子串,分别为:XED和BGA;

4.对XED和BGA(加上定位用的根节点A)分别重复步骤1 2 3,XED用于构建左子树,BGA用于构建右子树,直到所有的节点都用于构建树。

每执行完第一轮步骤1 2 3,所用的根节点已经用于构建树了,后续就不用再考虑了。例如,执行完第一轮步骤1 2 3,根节点F已经用过了,后续就不用再考虑了。

分析:

相信思路都很明确,步骤大概也明白了,接下来代码实现中一个非常注重细节的地方就是递归构建左子树和右子树的部分,再详细说就是在递归调用构建树的函数中,我们要传入的两个参数应该怎么确定。

本次主要介绍利用先序遍历序列和后序遍历序列构建一个二叉树并输出中序遍历的方法,我们在递归调用构建树的函数中,我们要传入的两个参数当然就是子树的先序遍历序列和后序遍历序列。创建左子树时就传入左子树的先序遍历序列和后序遍历序列,创建右子树时就传入右子树的先序遍历序列和后序遍历序列。

以下根据以上案例详细分析:对于:

索 引:0123456

先序遍历序列为:FDXEABG

中序遍历序列为:XEDBGAF

将以上两个遍历序列分别命名为字符串s1,s2,即s1 = "FDXEABG", s2 = "XEDBGAF"。

根据s1可知树的根root为F,根据s2可知树右子树的根rRoot为A,在s1中寻找到A的索引(定义为pos)为4。

根据s1可得左子树包括的字符有:DXE(由s1.substr(1, pos-1)获得),右子树包括的字符有:ABG(由s2.substr(pos)获得),

在s2中对应的字符串分别为:XED(由s2.substr(0, pos-1)获得)和BGA(由s2.substr(pos-1, str1.size() - pos)获得)。

根据以上获得的四个参数,可以递归创建左子树和右子树。

源代码:

//根据先序遍历和后序遍历确定一个二叉树,但必须是满二叉树
// 二叉树节点结构定义
struct TreeNode {
	char data;
	TreeNode* leftChild;
	TreeNode* rightChild;
	TreeNode(char c) : data(c), leftChild(NULL), rightChild(NULL) {}
};

// 根据先序遍历和后序遍历构建满二叉树
TreeNode* Build(string str1, string str2) {
	if (str1.size() == 0) {
		return NULL;
	}
	// 取先序遍历的第一个字符作为根节点
	//根节点可以根据先序遍历的第一个字符和后序遍历的最后一个字符直接获得
	TreeNode* root = new TreeNode(str1[0]);
	//当先序遍历中只剩下一个节点时,已经在前面的创建子树的作为根节点使用过了,就不需要再做处理了
	if (str1.size() > 1) {
		// 在后序遍历中找到左子树根节点的位置
		char c = str2[str2.size() - 2];
		// 在先序遍历中找到根节点的位置
		int pos = str1.find(c);
		// 递归构建左子树
		root->leftChild = Build(str1.substr(1, pos - 1), str2.substr(0, pos - 1));
		// 递归构建右子树
		root->rightChild = Build(str1.substr(pos), str2.substr(pos - 1, str1.size() - pos));
	}

	return root;
}

//中序遍历
void InOrder(TreeNode* root) {
	if (root == NULL) {
		return;
	}
	// 先遍历左子树
	InOrder(root->leftChild);
	//输出当前节点的值
	cout << root->data;
	// 再遍历右子树
	InOrder(root->rightChild);

	return;
}

int main()
{
	string s1, s2;
	while (getline(cin, s1)) {
		getline(cin, s2);
		// 根据先序遍历和后序遍历递归构建满二叉树
		TreeNode* root = Build(s1, s2);
		// 中序遍历该满二叉树
		cout << "中序遍历结果为:";
		InOrder(root);
		cout << endl;
	}

	return 0;
}

示例运行结果:

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/908904.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

股票委托接口的部分源码分析(一)

对于一些股票委托接口的源码分析需要具体指定的交易系统可能有不同的接口实现。以下是对一个常见的股票委托接口实现的源码分析示例&#xff1a; import requestsdef place_order(symbol, price, quantity, side): url https://example.com/api/place_order payload {…

gRPC 客户端调用服务端需要连接池吗?

发现的问题 在微服务开发中&#xff0c;gRPC 的应用绝对少不了&#xff0c;一般情况下&#xff0c;内部微服务交互&#xff0c;通常是使用 RPC 进行通信&#xff0c;如果是外部通信的话&#xff0c;会提供 https 接口文档 对于 gRPC 的基本使用可以查看文章 gRPC介绍 对于 g…

ClickHouse(二十三):Java Spark读写ClickHouse API

进入正文前&#xff0c;感谢宝子们订阅专题、点赞、评论、收藏&#xff01;关注IT贫道&#xff0c;获取高质量博客内容&#xff01; &#x1f3e1;个人主页&#xff1a;含各种IT体系技术&#xff0c;IT贫道_Apache Doris,大数据OLAP体系技术栈,Kerberos安全认证-CSDN博客 &…

vue开发环境搭建(WebStorm)

一、安装Node.js&#xff0c;搭建Vue环境 1、访问Node.js官网&#xff08;https://nodejs.org/en/download/&#xff09;进行安装包下载。 2、下载成功之后运行安装程序&#xff0c;进行安装。 如果是用安装程序进行安装&#xff0c;在安装过程中会自动进行Nodejs环境变量的配置…

最新两年工作经验总结

最新两年工作经验总结 前言URP的使用1&#xff1a;如何开启URP1、老项目升级为URP2、创建新项目时选择URP创建 2&#xff1a;URP阴影的设置 PolyBrush的使用&#xff08;地图编辑插件&#xff09;制作山峰or低谷边缘柔化雨刷上色制造场景中的物体贴图地形创建容易踩坑的点ProBu…

springboot大文件上传、分片上传、断点续传、秒传的实现

对于大文件的处理&#xff0c;无论是用户端还是服务端&#xff0c;如果一次性进行读取发送、接收都是不可取&#xff0c;很容易导致内存问题。所以对于大文件上传&#xff0c;采用切块分段上传&#xff0c;从上传的效率来看&#xff0c;利用多线程并发上传能够达到最大效率。 …

示例1:FreeRTOS移植详解_基于HAL库工程

1、开发环境 (1)Keil MDK: V5.38.0.0 (2)STM32CubeMX: V6.8.1 (3)MCU: STM32F103C8(F1系列软仿真最方便) (4)ARM编译器&#xff1a;V5(使用V6编译会报错) 2、移植准备工作 (1)用于移植FreeRTOS的基础工程。 时钟已配置好串口已配置好printf已经重定向到串口1 (2)FreeRT…

《YOLO小目标检测》专栏介绍 CSDN独家改进创新实战专栏目录

&#x1f4a1;&#x1f4a1;&#x1f4a1;Yolo小目标检测&#xff0c;独家首发创新&#xff08;原创&#xff09;&#xff0c;适用于Yolov5、Yolov7、Yolov8等各个Yolo系列&#xff0c;专栏文章提供每一步步骤和源码&#xff0c;带你轻松实现小目标检测涨点 &#x1f4a1;&…

【二分查找篇】速刷牛客TOP101 高效刷题指南

文章目录 17、BM17 二分查找-I18、BM18 二维数组中的查找19、BM19 寻找峰值20、BM20 数组中的逆序对21、BM21 旋转数组的最小数字22、BM22 比较版本号23、BM23 二叉树的前序遍历 17、BM17 二分查找-I 思路步骤&#xff1a; step 1&#xff1a;从数组首尾开始&#xff0c;每次取…

wustojc日期格式变化

#include <stdio.h> int main() {char a[10];for(int i0;i<10;i){//用一个耍聪明的方法&#xff0c;全部用数组存储&#xff1b;面向结果编程a[0]getchar();}printf("%c%c%c%c%c%c%c%c%c%c",a[6],a[7],a[8],a[9],a[2],a[0],a[1],a[5],a[3],a[4]);return 0;}…

什么是跳跃表 ? 说一说跳跃表的查询和新增流程 ?

1.什么是跳跃表&#xff08;Skip List&#xff09; 跳跃表是 ZSet 有序列表底层的一种实现&#xff0c;也成为跳表。它通过添加多层链表的方式&#xff0c;用于在有序集合中进行高效的查找操作。 简单跳跃表的结构图&#xff1a; 从图中可以看出跳跃表有这些特征&#xff1a; …

Nginx-URLRewrite伪静态

URLRwrite是指将真实地址隐藏&#xff0c;用户访问是通过伪地址进行访问&#xff0c;这样可以隐藏URL中的传参等等 URLwrite演示&#xff0c;浏览器输入伪URL&#xff0c;回车会跳转到真实URL Rewrite匹配规则 redirect是指当请求伪装地址后&#xff0c;页面会直接跳转到真实…

基于微信小程序的上门维修评价系统_22c7h-

随着科学研究的不断深入&#xff0c;有关上门维修的各种信息量也在成倍增长。面对庞大的信息量&#xff0c;就需要有上门维修系统来提高管理工作的效率。通过这样的系统&#xff0c;我们可以做到信息的规范管理和快速查询&#xff0c;从而减少了管理方面的工作量。 建立基于微信…

聊聊 Docker

聊聊 Docker Docker 是什么&#xff1f; 定义 Docker 是一款 开源的应用容器引擎。 简单来说&#xff0c;就是 以容器虚拟化技术为基础的软件。可以把应用程序和所依赖的包一起打包到一个可移植的镜像中&#xff0c;发布到 Linux 或者 Windows 上运行。&#xff08;代码 运…

数据通信——传输层(传输层概述)

引言 终于到传输层了&#xff0c;网络层还有很多需要补充的&#xff0c;后期在慢慢填补了。 我们看哈&#xff01;在物理层我们设计出来各种硬件&#xff0c;然后使它们在物理上相互连接&#xff0c;信号以比特流的形式进行发送&#xff1b;随后&#xff0c;在数据链路层&#…

Mybatis介绍和搭建(详细搭建步骤)

目录 一、mybatis介绍 官方简介 通俗易懂 二、搭建步骤 1.创建Maven项目 2.创建数据库并建表和相关类 3.创建全局配置文件,配置数据库连接信息 4.配置sql映射文件 5.测试 一、mybatis介绍 官方简介 MyBatis 是一款优秀的持久层框架&#xff0c;它支持自定义 SQL、存…

C语言和JavaScript中的默认排序行为对比

前言 今天在js里使用sort时遇见了一个不理解的现象 即使用sort默认排序后 9 从排序前的第一位被排到了最后一位.一开始我对js sort的理解和c一样&#xff0c;然后通过查阅后发现并不是这样. 正文 排序是一项常见而重要的操作。不同的编程语言提供了不同的排序函数&#xf…

Vue开发中如何解决国际化语言切换问题

Vue开发中如何解决国际化语言切换问题 引言&#xff1a; 在如今的全球化时代&#xff0c;应用程序的国际化变得越来越重要。为了让不同地区的用户能够更好地使用应用程序&#xff0c;我们需要对内容进行本地化&#xff0c;以适应不同语言和文化环境。对于使用Vue进行开发的应用…

ROS2 中的分布式系统

一、说明 当您运行 ROS2 应用程序时&#xff0c;通常需要在不同机器的不同位置运行 ROS2 节点。由于 ROS2 在抽象的 DDS 层中使用节点之间的通信&#xff0c;因此我们可以非常轻松地安排通信。 为了充分理解 ROS2 的架构&#xff0c;我建议您熟悉本文。 出于本文的目的&#xf…

Java 计算生肖,java Data中获取年,根据生日日期获取生肖注解,根据输入时间获取生肖,自定义注解的方式获取生肖 根据年份时间获取十二生肖

最近&#xff0c;开发中需要增加生肖&#xff0c;但是不想增加字段&#xff0c;于是通过注解的方式&#xff0c;实现生日与生肖的转换。 话不多说&#xff0c;直接上代码&#xff0c;如下&#xff1a; 实体类中的字段&#xff0c;添加自定义注解&#xff08;ToChineseZodiacSe…