【算法】【树】已知先序中序序列求后序序列(详细解释)
题目描述
如题所示,已知先序中序序列建树与求后序序列
算法原理
利用递归和分制的思想,找到当前树先序序列的根节点,然后找到对应中序序列的位置,然后根据根节点在中序序列中的位置来判断左右子树分别的位置,然后继续对左右子树进行递归,最后得出结果
post(0, 0, 序列总长度-1);
void post(int root, int start, int end)
首先是递归函数进入,其中三个形参分别代表的含义为
root 先序序列中当前递归层中根节点的下标
start 中序序列中子树的最左下标(子树开始的下标)
end 中序序列中子树的最右下标(子树结束的下标)
if(start > end) return ;
递归结束的标志,因为子树的元素范围在下标[start,end]之内,当start>end的时候,说明以当前节点为空节点
int i = start;
这里的i相当于只在中序遍历中有效,这里的i对于查找根节点root的先序序列完全没有意义,仅代表root在中序序列中的下标位置
例子:
假设一棵二叉树为上面的形式,那么他的先序序列和中序序列为
先序序列 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
中序序列 | 4 | 3 | 5 | 2 | 7 | 6 | 8 | 1 | 10 | 9 | 11 |
递归原理:
重点要解释一下这里的两条递归语句,分别代表递归当前根节点的左子树和当前根节点的右子树
对于左子树
post(root + 1, start, i - 1); //递归左子树
根节点 | 左子树 | 右子树 | |||||||||
先序序列 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
root | root+1 | ||||||||||
根节点 | 左子树的根节点 | ||||||||||
左子树 | 根节点 | 右子树 | |||||||||
中序序列 | 4 | 3 | 5 | 2 | 7 | 6 | 8 | 1 | 10 | 9 | 11 |
i-1 | i | ||||||||||
start | end |
如图可见,当遍历左子树的时候,
对于先序序列,左子树的根节点为先序序列上一层根节点root的下一个节点,也就是root+1
对于中序序列,因为是左子树,所以启始start值不变,end应该为在中序序列中找到的根节点i的前一个节点也就是i-1
对于右子树
post(root + 1 + i - start, i + 1, end);
根节点 | 左子树 | 右子树 | |||||||||
先序序列 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
root | root+1 | root+(i-start) | root+(i-start)+1 | ||||||||
根节点 | 左子树的根节点 | ||||||||||
左子树的元素个数=i-start | |||||||||||
左子树 | 根节点 | 右子树 | |||||||||
中序序列 | 4 | 3 | 5 | 2 | 7 | 6 | 8 | 1 | 10 | 9 | 11 |
i-1 | i | i+1 | |||||||||
start | end |
中序序列中的启始位置和结束位置都比较好确定,启始位置为i+1,结束位置为end
主要的难点就在于root的确认,我们能知道在先序序列中,是按照根节点——左子树——右子树排列的,左子树的根节点在先序序列中就为本层的根节点+1(root+1),比较好确定,但是右子树的跟节点就没有那么好确认了,但是我们细想就可以知道,原本的根节点加上左子树的节点个数,那不就到了右子树了嘛,但是这个想法也不准确
首先左子树的节点个数可以根据中序序列来判断,为i-start,但是根节点加上左子树的节点总数(root+(i-start))仅仅代表了左子树的最右侧节点,再加1才能代表右子树的第一个端点
有这幅图就可以比较清楚的看出
那么就引出了另一个问题了为什么根节点不能直接是i+1,而是要绕这么大一个圈子回来呢?
这就需要下一步递归来判断了
父节点的左子树 | |||||||||||
父节点 | 新的根节点 | 左子树 | 右子树 | 父节点的右子树子树 | |||||||
先序序列 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
root | |||||||||||
父节点的左子树 | |||||||||||
左子树 | 新的根节点 | 右子树 | 父节点 | 父节点的右子树 | |||||||
中序序列 | 4 | 3 | 5 | 2 | 7 | 6 | 8 | 1 | 10 | 9 | 11 |
i-1 | i | i+1 | |||||||||
start | end |
这样就比较容易能看出来了,正确的根节点应该是6
但是i+1仅仅表示7,明显与答案不符
实际上i仅仅在中序序列中有意义,放在先序序列中并没有什么意义
核心代码实现
参考柳婼已知前序(先序)与中序输出后序_柳婼 の blog-CSDN博客
#include <cstdio>
using namespace std;
int pre[] = {1,2,3,4,5,6,7,8};
int in[] = {4,3,5,2,7,6,8,1};
void post(int root, int start, int end) {//root 先序序列中当前递归层中根节点的下标//start 中序序列中子树的最左下标(子树开始的下标)//end 中序序列中子树的最右下标(子树结束的下标)if(start > end) return ; /*递归结束的标志,因为子树的元素范围在下标[start,end]之内,当start>end的时候,说明以当前节点为空节点*/int i = start; //这里的i对于查找根节点root的先序序列完全没有意义,仅代表root在中序序列中的下标位置while(i < end && in[i] != pre[root]) i++; //寻找root在中序序列中的位置post(root + 1, start, i - 1); //递归左子树post(root + 1 + i - start, i + 1, end); //递归右子树printf("%d ", pre[root]); //输出后序序列
}int main() {post(0, 0, 7);//这里的总长度是pre.size()-1,而不是pre.size()return 0;
}
例题
【算法】【树】已知先序中序序列求后序序列(详细解释)相关推荐
- 数据结构----二叉树已知先序和中序遍历序列求后序遍历
说明 通过先序和中序或者中序和后序我们可以还原出原始二叉树,但是通过先序和后序是无法还原出原始二叉树也即是说,只有通过先序和中序,或者中序和后序我们才可以唯一的确定一个二叉树. 例子一 已知先序和中序 ...
- 已知二叉树先序和中序遍历结果,求后序遍历结果
以下面的例题为例进行讲解:已知一棵二叉树的先序遍历序列和中序遍历序列分别是ABDCEF.BDAECF,求二叉树及后序遍历序列. 分析:先序遍历序列的第一个字符为根结点.对于中序遍历,根结点在中序遍历序 ...
- 给出中序和前序求后序Java,已知二叉樹前序,中序遍歷,求后序遍歷,java實現...
簡單介紹一下思想,先看前序,前序遍歷的第一個節點,就是該樹的根.在中序中找到該根的位置,設為index,在中序遍歷集合中,位於index之前的屬於根的左子樹,位於index之后的屬於根的右子樹.然后, ...
- 二叉树面试题:前中序求后序、中后序求前序
在面试时,避免不了的会遇到一些数据结构的面试题,今天我们就来了解一下二叉树的经典面试题: 已知二叉树的前序遍历顺序为ABDCEGHF,中序遍历顺序为DBAGEHCF,求该二叉树的后序遍历. 还有: 已 ...
- 已知一棵二叉树的中序序列和后序序列,写一个建立该二叉树的二叉链表存储结构的算法...
已知一棵二叉树的中序序列和后序序列,写一个建立该二叉树的二叉链表存储结构的算法 #define N 10 //二叉树节点的个数 char postorderstr[]={};//后序序列 char i ...
- [算法] 已知前序和中序遍历,建立二叉树
结点结构 typedef struct Node{char data;struct Node *left;struct Node *right; }Node; 已知前序和中序遍历顺序,建立二叉树 问题 ...
- 二叉树:已知先序和中序求后序,已知中序和后序求先序
树的三种遍历方式的遍历顺序: 先序遍历:根.左子树.右子树(特点:第一个元素为根) 中序遍历:左子树.根.右子树(特点:根的两边分别为左子树和右子树) 后序遍历:左子树.右子树.根(特点:最后一个元素 ...
- C++实现已知二叉树前序遍历和中序遍历,求后序遍历
C++实现已知二叉树前序遍历和中序遍历,求后序遍历 一.基本概念 1.先序遍历(NLR)可以确定二叉树的父子结点: 2.中序遍历(LNR)可以确定二叉树的左右子树: 3.后序遍历(LRN)可以确定二叉 ...
- PAT甲级1020变体:已知二叉树层序+中序序列,求后序遍历序列
PAT甲级1020变体:已知二叉树层序+中序序列,求后序遍历序列 题目 输入格式 输出格式 输入样例 输出样例 代码 题目 已知二叉树层序+中序序列,求后序遍历序列. 输入格式 第一行给出该二叉树的节 ...
最新文章
- ubuntu下解决oracle sqlplus不能查看历史命令问题
- 最高效的回文数(C语言实现)
- JAVA 泛型中的通配符 T,E,K,V,?
- python如何提高工作效率_用Python的这3个优点,让工作效率提升一倍
- python如何创建txt_如何通过读取.txt文件为每个键创建包含多个“列表”的Python字典?...
- 数据库原理(一)—— 关系代数
- C/C++开发_C语言里类似C++的构造与析构
- ffmpeg CLI常用命令
- huffman树_Java使用哈夫曼树实现文件压缩的原理及实现
- conda可以更改环境的python anaconda替换环境的Python
- 中国 AI 天才养成计划:清华姚班和 100 个「张小龙」
- matlab中带脚咪头怎么找,咪头用万能表怎么测_咪头怎么辨认正负极
- 统计学 | 八大经典思想「AI核心算法」
- CSS基础 | (1) CSS是什么
- 新媒体下旅游目的地营销研究――以安徽省灵璧县为例
- Sulley fuzzer learning
- 线性泛函分析之对偶基
- Mysql8.0和Mysql5.0访问jdbc连接
- php查询替换_如何在PHP中使用正则表达式进行查找替换
- Axure电商后台业务管理系统原型模板+app电商原型交互+移动端电商通用PRD文档+全局交互用例说明+Axure高保真电商社交prd文档+电商prd+电商需求文档+订单、购物车、配货、物流、仓储
热门文章
- python的pandas重复值处理(duplicated()和drop_duplicates())
- BACnet协议读取与发送
- matlab 三维动态,matlab三维动态绘图
- 转行程序员需要做好哪些准备?只有这种人能成功转行ǃ
- 关于RC阻容复位电路的问题
- gsoc 任务_gsoc 2020与cern hsf暗物质和深度学习
- 【error】_smartbi数据集超出最大行数: DataRows > 1000
- 网络发现自动关闭不能启用、无法启用文件和打印共享的解决办法
- 笔记本固态盘数据丢失怎么办?笔记本固态盘怎么恢复数据
- window server2008下安装VS.NET2008