【算法/c++】利用中序遍历和后序遍历建二叉树

目录

  • 题目:树的遍历
    • 前言
    • 题目来源
    • 树的数组存储
      • 基本思想
      • 存储规则
      • 示例
    • 建树算法
      • 关键思路
      • 代码
      • 总代码
    • 链表法

题目:树的遍历

前言

如果不是完全二叉树,使用数组模拟树,会很浪费空间。

题目来源

本题来自 PTA 天梯赛。
题目链接: 树的遍历

题目描述
给定一棵二叉树的后序遍历和中序遍历序列,输出其层序遍历的序列。假设树中节点的键值均为互不相同的正整数。

输入格式

  • 第一行:一个正整数 N(≤30),表示二叉树的节点个数。
  • 第二行:后序遍历序列,数字间以空格分隔。
  • 第三行:中序遍历序列,数字间以空格分隔。

输出格式

  • 输出层序遍历序列,数字间以 1 个空格分隔,行首尾不得有多余空格。

输入样例

7
2 3 1 5 7 6 4
1 2 3 4 5 6 7

输出样例

4 1 6 3 5 7 2

树的数组存储

基本思想

通过数组的索引关系表示树的父子结构,无需显式存储指针。

存储规则

  1. 根节点存储在索引 1(注意不是 0)。
  2. 对于任意节点 i
    • 左子节点索引2 * i
    • 右子节点索引2 * i + 1
    • 父节点索引i / 2(整数除法)

示例

假设有一棵二叉树:
在这里插入图片描述
我们可以通过一个数组去存储
在这里插入图片描述
树的索引对应数组的索引,树节点的值存在数组里。

建树算法

关键思路

  • 后序遍历:最后一个元素是根节点
  • 中序遍历:根节点左边是左子树,右边是右子树
  • 递归构建:分别处理左右子树

后序遍历:
结构: 左子树 — 右子树 — 根

中序遍历:
结构: 左子树,根,右子树

我们通过中序遍历找到根,就能知道左子树的个数,那么我们就能找到后序遍历左子树的范围,从而得知左子树的根。右子树同理。

算法过程:

1.确定根节点:

  • 从后序遍历序列中取出最后一个元素,这就是当前子树的根节点
  • 将这个根节点存入我们构建的树结构中

2.在中序序列中定位根节点:

  • 在中序遍历序列中查找这个根节点的位置
  • 这个位置将中序序列分为左子树和右子树两部分

3.递归构建左右子树

代码

参数说明

  • root 后序序列中当前子树的根节点索引
  • start 中序序列中当前子树的起始索引
  • ed 中序序列中当前子树的结束索引
  • idx 当前节点在tree数组中的存储位置

变量说明

  • post 为后序遍历数组
  • in 为中序遍历数组
  • tree为存储树的数组
//根据中序遍历和后续遍历构造树
void build(int root,int start,int ed,int idx)
{if(start>ed) return;//后序知道树根,直接构造数组树tree[idx] = post[root];//在中序遍历中找根位置,用来区分后序遍历左右子树位置int i = start;while(i<ed && in[i] != post[root]) i++;//构造左子树build(root - ed+i-1,start,i-1,idx*2);//构造右子树build(root - 1,i+1,ed,idx*2+1);
}

总代码

#include <iostream>
using namespace std;
#include <vector>const int N = 1e5+10;
int n;
int post[N],in[N];
vector<int> tree(N,-1);//根据中序遍历和后续遍历构造树
void build(int root,int start,int ed,int idx)
{if(start>ed) return;//后序知道树根,直接构造数组树tree[idx] = post[root];//在中序遍历中找根位置,用来区分后序遍历左右子树位置int i = start;while(i<ed && in[i] != post[root]) i++;//构造左子树build(root - ed+i-1,start,i-1,idx*2);//构造右子树build(root - 1,i+1,ed,idx*2+1);
}int main()
{cin  >> n;for(int i = 1;i<=n;i++)cin >>  post[i];for(int i = 1;i<=n;i++)cin >> in[i];build(n,1,n,1);vector<int> ans;for(int i = 1;i<tree.size();i++)if(tree[i] !=-1) ans.push_back(tree[i]);for(int i = 0;i<ans.size();i++)if(i != ans.size()-1)cout << ans[i]  <<  ' ';else cout << ans[i];return 0;
}

链表法

思路是差不多的

#include <iostream>
#include <queue>using namespace std;
const int N  =50;
int n;
int post[N],in[N];struct node
{int val;node* left;node* right;
};node* build(int root,int start,int ed)
{if(start>ed) return nullptr;//创建结点node * p = (node *) malloc(sizeof(node));p->val = post[root];//在中序遍历中找根位置,用来区分后序遍历左右子树位置int i = start;while(i<ed && in[i] != post[root]) i++;p->left = build(root - ed+i-1,start,i-1);p->right = build(root - 1,i+1,ed);return p;
}void dfs(node *p)
{queue<node> q;q.push(*p);while(q.size()){node temp = q.front();q.pop();if(temp.val != p->val)cout << " ";cout << temp.val;if(temp.left != nullptr)  q.push(*temp.left);if(temp.right != nullptr) q.push(*temp.right);} 
}int main()
{cin >> n;for(int i = 1;i<=n;i++)cin >>  post[i];for(int i = 1;i<=n;i++)cin >> in[i];node* head = build(n,1,n);dfs(head);return 0;
}

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

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

相关文章

李臻20242817_安全文件传输系统项目报告_第6周

安全文件传输系统项目报告&#xff08;第 1 周&#xff09; 1. 代码链接 Gitee 仓库地址&#xff1a;https://gitee.com/li-zhen1215/homework/tree/master/Secure-file 代码结构说明&#xff1a; project-root/├── src/ # 源代码目录│ ├── main.c # 主程序入口│ ├…

嵌入式rodata段

在嵌入式软件开发中&#xff0c;将数据放入只读数据段&#xff08;.rodata&#xff09;具有以下好处及典型应用示例&#xff1a; 好处 数据保护 .rodata段的内容在程序运行时不可修改&#xff0c;防止意外或恶意篡改&#xff0c;提升系统稳定性。 节省RAM资源 只读数据可直接…

InfoSec Prep: OSCP靶场渗透

InfoSec Prep: OSCP InfoSec Prep: OSCP ~ VulnHubInfoSec Prep: OSCP, made by FalconSpy. Download & walkthrough links are available.https://www.vulnhub.com/entry/infosec-prep-oscp,508/ 1&#xff0c;将两台虚拟机网络连接都改为NAT模式 2&#xff0c;攻击机上做…

【JavaWeb-Spring boot】学习笔记

目录 <<回到导览Spring boot1. http协议1.1.请求协议1.2.响应协议 2.Tomcat2.1.请求2.1.1.apifox2.1.2.简单参数2.1.3.实体参数2.1.4.数组集合参数2.1.5.日期参数2.1.6.(重点)JSON参数2.1.7.路径参数 2.2.响应2.3.综合练习 3.三层架构3.1.三层拆分3.2.分层解耦3.3.补充 &…

C++的多态-上

目录 多态的概念 多态的定义及实现 1.虚函数 2. 多态的实现 2.1.多态构成条件 2.2.虚函数重写的两个例外 (1)协变(基类与派生类虚函数返回值类型不同) (2)析构函数的重写(基类与派生类析构函数的名字不同) 2.3.多态的实现 2.4.多态在析构函数中的应用 2.5.多态构成条…

网络安全的重要性与防护措施

随着信息技术的飞速发展&#xff0c;互联网已经成为我们日常生活、工作和学习的必需品。无论是通过社交媒体与朋友互动&#xff0c;还是在网上进行银行交易&#xff0c;网络已经渗透到我们生活的方方面面。然而&#xff0c;随之而来的是各种网络安全问题&#xff0c;包括数据泄…

CMake学习--Window下VSCode 中 CMake C++ 代码调试操作方法

目录 一、背景知识二、使用方法&#xff08;一&#xff09;安装扩展&#xff08;二&#xff09;创建 CMake 项目&#xff08;三&#xff09;编写代码&#xff08;四&#xff09;配置 CMakeLists.txt&#xff08;五&#xff09;生成构建文件&#xff08;六&#xff09;开始调试 …

访问数组元素(四十四)

1. 数组下标与类型 数组的索引从 0 开始。例如&#xff0c;一个包含 10 个元素的数组&#xff0c;其合法下标范围为 0 到 9&#xff0c;而不是 1 到 10。为了表示下标&#xff0c;通常使用 size_t 类型&#xff0c;它是一种与机器相关的无符号整型&#xff0c;足够大以存放内存…

计算机网络 3-1 数据链路层(功能+组帧+差错控制)

【考纲内容】 &#xff08;一&#xff09;数据链路层的功能 &#xff08;二&#xff09;组帧 &#xff08;三&#xff09;差错控制 检错编码&#xff1b;纠错编码 &#xff08;四&#xff09;流量控制与可靠传输机制 流量控制、可靠传输与滑动窗口机制&#xff1b;停止-等…

Django中使用不同种类缓存的完整案例

Django中使用不同种类缓存的完整案例 推荐超级课程: 本地离线DeepSeek AI方案部署实战教程【完全版】Docker快速入门到精通Kubernetes入门到大师通关课AWS云服务快速入门实战目录 Django中使用不同种类缓存的完整案例步骤1:设置Django项目步骤2:设置URL路由步骤3:视图级别…

Spring Boot 集成Redis 的Lua脚本详解

1. 对比Lua脚本方案与Redis自身事务 对比表格 对比维度Redis事务&#xff08;MULTI/EXEC&#xff09;Lua脚本方案原子性事务命令序列化执行&#xff0c;但中间可被其他命令打断&#xff0c;不保证原子性Lua脚本在Redis单线程中原子执行&#xff0c;不可中断计算能力仅支持Red…

【大模型】DeepSeek + 蓝耕MaaS平台 + 海螺AI生成高质量视频操作详解

目录 一、前言 二、蓝耘智能云MaaS平台介绍 2.1 蓝耘智算平台是什么 2.2 平台优势 2.3 平台核心能力 三、海螺AI视频介绍 3.1 海螺AI视频是什么 3.2 海螺AI视频主要功能 3.3 海螺AI视频应用场景 3.4 海螺AI视频核心优势 3.5 项目git地址 四、蓝耘MaaS平台DeepSeek海…

12-产品经理-维护模块

需求模块是帮助产品经理进行需求的分类和维护。 1. 维护模块 在具体产品的“研发需求”页面左侧&#xff0c;点击“维护模块”。也可以在具体产品的“设置”-“模块”下进行维护。 点击保存后&#xff0c;返回模块页面。还可以点击“子模块”对已有模块进行子模块的维护。 点击…

考研单词笔记 2025.04.06

area n领域&#xff0c;范围&#xff0c;方面&#xff0c;地区&#xff0c;地方&#xff0c;场地&#xff0c;面积 aspect n方面&#xff0c;层面&#xff0c;外表&#xff0c;外观 boundary n限度&#xff0c;界限&#xff0c;分界线&#xff0c;边界 cap n最高限额&#x…

护网蓝初面试题

《网安面试指南》https://mp.weixin.qq.com/s/RIVYDmxI9g_TgGrpbdDKtA?token1860256701&langzh_CN 5000篇网安资料库https://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247486065&idx2&snb30ade8200e842743339d428f414475e&chksmc0e4732df793fa3bf39…

玄机-apache日志分析

靶场任务 1、提交当天访问次数最多的IP&#xff0c;即黑客IP&#xff1a; 查看apache日志 apache访问日志的位置是&#xff1a;/var/log/apache2/access.log.1 匹配正则算法 首先先cat看看 发现地址都在第一行&#xff0c;直接匹配计算输出 cat access.log.1 |grep -Eo &…

C++ I/O 流通俗指南

1. std::ostream 是什么&#xff1f; 定义&#xff1a;std::ostream 是 C 标准库中的输出流类&#xff0c;负责将数据输出到各种目标&#xff08;如屏幕、文件、网络等&#xff09;。你可以把 std::ostream 想象成一根“数据水管”&#xff1a; 数据从 C 代码流进 std::ostrea…

Systemd 使用教程(二):Unit 的概念

目录 【二】 Systemd 单元&#xff08;Unit&#xff09;的概念 本教程将由浅入深的介绍 linux 中 Systemd 的知识和相关使用&#xff08;同时也方便自己后续查阅&#xff09; 【二】 Systemd 单元&#xff08;Unit&#xff09;的概念 虽然我想介绍的比较偏实际操作&#xff0…

树莓派PICO 设备烧录成cmsis dap

文章目录 1. 实际操作2. IO连接 1. 实际操作 2. IO连接

IntelliJ IDEA中Spring Boot 3.4.x+集成Redis 7.x:最新配置与实战指南

‌前言 Spring Boot 3.4.x作为当前‌最新稳定版本‌&#xff0c;全面支持Java 17与Jakarta EE 10规范。本文以‌Spring Boot 3.4.1‌和‌Redis 7.x‌为例&#xff0c;详解如何在IDEA中快速接入Redis&#xff0c;涵盖‌最新依赖配置‌、‌数据序列化优化‌、‌缓存注解‌及‌高…