news 2026/7/23 17:38:43

【例3-4】求后序遍历(信息学奥赛一本通- P1339)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【例3-4】求后序遍历(信息学奥赛一本通- P1339)

【题目描述】

输入一棵二叉树的先序和中序遍历序列,输出其后序遍历序列。

【输入】

共两行,第一行一个字符串,表示树的先序遍历,第二行一个字符串,表示树的中序遍历。树的结点一律用小写字母表示。

【输出】

一行,表示树的后序遍历序列。

【输入样例】

abdec dbeac

【输出样例】

debca

【算法笔记】由先序和中序遍历还原二叉树:别死记下标,一张草稿纸搞定

在二叉树的题目里,“已知先序和中序,求后序”属于必考的基本功。

很多同学逻辑都懂:先序找根,中序分左右。但在写代码时,往往死在递归的下标边界计算上。到底是+1还是-1?左子树的长度怎么算?一不小心就写出个死循环。

今天结合一张手写草稿,带大家彻底理顺这个逻辑,并给出顺序存储链式存储两种标准写法。

1. 核心思路:对着草稿推下标

看先序a b d e c和中序d b e a c

  • 先序第一个a是根。

  • 去中序里找到a的位置,它左边的d b e是左子树,右边的c是右子树。

难点在于:如何在先序序列里,把左子树那一段精准地“抠”出来?

关键变量定义

我们在递归函数dfs(la,ra,lb,rb)中定义:

  • la,ra:当前子树在先序中的起点和终点。

  • lb,rb:当前子树在中序中的起点和终点。

  • root:根节点在中序里的下标(用 string 的 find 找到)。

必考逻辑(请理解并背诵)

  1. 左子树有多长?

    看中序序列,从 lb 开始到 root 前面。

    所以,左子树长度 (len) = root - lb。

    (这一步算错,后面全错)

  2. 左子树的范围(递归左儿子)

    • 中序:很明显是[lb, root-1]

    • 先序:起点是根的下一个la+1。终点是起点加上长度。

    • 也就是:[la+1, la+root-lb]

  3. 右子树的范围(递归右儿子)

    • 中序:很明显是[root+1, rb]

    • 先序:紧接着左子树后面。

    • 起点:左子树终点 + 1。也就是la+(root-lb)+1

    • 终点:直接就是ra


2. 方法一:顺序存储(完全二叉树思维)

利用完全二叉树性质:节点k的左儿子下标是2*k,右儿子是2*k+1

  • 优点:逻辑简单。

  • 缺点极其浪费空间。如果是“歪脖子树”(退化成链),空间复杂度是 2^N。除非确定节点少或者满二叉树,否则慎用。

//先建树 再后序遍历输出 //方法一:顺序存储 //特点:利用2*k和2*k+1计算位置 #include<bits/stdc++.h> using namespace std; string a,b;//先序遍历 中序遍历 struct node{ int l;//记录左儿子节点的下标 int r;//记录右儿子节点的下标 char data; node(){ l=r=0; } }tre[4000];//顺序存储一定要开大数组,防止越界 void postorder(int root){//后序输出 if(tre[root].l!=0) postorder(root*2); if(tre[root].r!=0) postorder(root*2+1); cout<<tre[root].data; } void dfs(int la,int ra,int lb,int rb,int k){ //k代表所建树中根节点的下标 la ra代表本次先序遍历的起点终点 //lb rb代表本次中序遍历的起点终点 if(la>ra||lb>rb) return; int root=b.find(a[la]);//找到根节点在中序遍历输出中的位置 tre[k].data=a[la];//顺序存储记录根节点的数据 if(root>lb){//代表有左子树 tre[k].l=2*k;//顺序存储的特点 //左子树长度=root-lb,所以先序终点=la+(root-lb) dfs(la+1,la+root-lb,lb,root-1,k*2); } if(root<rb){//代表有右子树 tre[k].r=2*k+1;//顺序存储的特点 //右子树先序起点=la+左子树长度+1 dfs(la+root-lb+1,ra,root+1,rb,2*k+1); } } int main(){ cin>>a>>b; int ra=a.size(); int rb=b.size(); dfs(0,ra-1,0,rb-1,1); postorder(1); return 0; }

3. 方法二:链式存储(静态数组模拟)

打比赛最推荐的写法。

不依赖 2*k,而是用一个全局计数器 ind,用一个申请一个。哪怕树退化成一条链(世代单传二叉树),空间复杂度也只是 O(N)。

  • 原理:每次++ind给新节点发一个“身份证号”,父节点把这个号码记在lr里。

//方法二:链式存储(静态数组池) //特点:空间利用率高,通用性强 #include<bits/stdc++.h> using namespace std; string a,b; struct node{ int l; int r; char data; node(){l=r=0;} }tre[1000]; int ind=1;//链式存储存放结点位置 void postorder(int root){ if(tre[root].l!=0) postorder(tre[root].l); if(tre[root].r!=0) postorder(tre[root].r); cout<<tre[root].data; } void dfs(int la,int ra,int lb,int rb,int k){ int root=b.find(a[la]);//找到根节点在b中的位置下标 tre[k].data=a[la]; if(root>lb){//如果左子树存在 tre[k].l=++ind;//链式存储的特点:申请新节点 dfs(la+1,la+root-lb,lb,root-1,ind); } if(root<rb){//代表右子树存在 tre[k].r=++ind;//链式存储的特点:申请新节点 dfs(root-lb+la+1,ra,root+1,rb,ind); } } int main(){ cin>>a>>b; int ra=a.size()-1; int rb=b.size()-1; dfs(0,ra,0,rb,1); postorder(1); return 0; }

4. 避坑总结

  1. 关于下标:千万别死记la+root-lb这种一长串的东西。考试时像我一样在草稿纸上画一段,算出左子树长度,然后根据“起点+长度”去推,绝对不会错。

  2. 关于存储

    • 如果是平时练习或者题目保证是完全二叉树 ->用方法一(写得快)。

    • 如果是正式比赛或者不确定树的形状 ->必用方法二(稳,不爆内存)。

  3. 关于代码风格:大家注意看,我在顺序存储里也保留了tre[k].l=2*k。虽然这一步可以通过计算省略,但加上去之后,它和链式存储的逻辑就完全统一了,非常适合理解“二叉树的本质”。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/23 0:26:40

全员 RTO5 政策,TikTok 开卷?

TikTok 开卷&#xff1f; TikTok 虽然和抖音性质类似&#xff0c;母公司也都是字节跳动。 但两者的工作节奏&#xff0c;其实差异挺大&#xff0c;毕竟 TikTok 的主要办公地点&#xff0c;是在美国洛杉矶或新加坡。 一些海外 IT 公司常见的福利待遇&#xff0c;TikTok 还是享受…

作者头像 李华
网站建设 2026/7/22 15:02:55

JSP如何结合AES加密实现大文件上传存储?

文件管理系统毕业设计&#xff1a;从零到崩溃的全过程 1. 我的毕业设计困境 "卧槽&#xff0c;这毕业设计是要我命啊&#xff01;"当我看到老师给出的文件管理系统需求时&#xff0c;差点把刚买的珍珠奶茶喷出来。 10G大文件上传&#xff1f;断点续传&#xff1f;…

作者头像 李华
网站建设 2026/7/23 6:26:53

毕业设计项目 基于机器视觉的目标跟踪算法

文章目录 0 前言2 目标跟踪效果3 目标跟踪的两种方法3.1 方法13.2 方法2 4 Tracking By Detecting的跟踪过程4.1 存在的问题4.2 基于轨迹预测的跟踪方式 5 训练代码6 最后 0 前言 &#x1f525; 今天学长向大家分享一个毕业设计项目 为了大家能够顺利以及最少的精力通过毕设&…

作者头像 李华
网站建设 2026/7/21 20:18:10

【大模型预训练】15-分布式训练概述:解决单机算力瓶颈的核心技术路径

引言分布式训练是现代深度学习中解决单机算力瓶颈的核心技术路径之一。随着深度学习模型的复杂性和数据量的急剧增加&#xff0c;传统的单机训练方式已难以满足高效计算的需求。分布式训练通过将计算任务分配到多个计算节点上&#xff0c;协同完成模型的训练过程&#xff0c;从…

作者头像 李华
网站建设 2026/7/23 11:08:12

重构智慧书-第10条:名声与好运

一、原文呈现名声与好运一个经久不衰&#xff0c;一个流转不定。前者常跚跚来迟&#xff0c;后者可助人乐生。好运须防他人嫉妒;名声须防湮没无闻。你可以诚心求好运有时亦可努力促成之;然一切名声无不以持之以恒的苦干为本。求名的愿望植根于力量与旺盛的精力。从古到今&#…

作者头像 李华
网站建设 2026/7/23 12:09:25

门槛低、含金量高!2026大专计算机专业必考8大证书

各位计算机专业的大专同学&#xff0c;你是否在求职时感到学历竞争力不足&#xff1f;别担心&#xff0c;证书是弥补学历短板、证明专业技能的最佳利器。选择报考门槛低、学习周期短、行业认可度高的证书&#xff0c;能为你带来极高的投资回报。一、 华为HCIA认证&#xff08;华…

作者头像 李华