题目描述

如题所示,已知先序中序序列建树与求后序序列

算法原理

利用递归和分制的思想,找到当前树先序序列的根节点,然后找到对应中序序列的位置,然后根据根节点在中序序列中的位置来判断左右子树分别的位置,然后继续对左右子树进行递归,最后得出结果

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;
}

例题

【算法】【树】已知先序中序序列求后序序列(详细解释)相关推荐

  1. 数据结构----二叉树已知先序和中序遍历序列求后序遍历

    说明 通过先序和中序或者中序和后序我们可以还原出原始二叉树,但是通过先序和后序是无法还原出原始二叉树也即是说,只有通过先序和中序,或者中序和后序我们才可以唯一的确定一个二叉树. 例子一 已知先序和中序 ...

  2. 已知二叉树先序和中序遍历结果,求后序遍历结果

    以下面的例题为例进行讲解:已知一棵二叉树的先序遍历序列和中序遍历序列分别是ABDCEF.BDAECF,求二叉树及后序遍历序列. 分析:先序遍历序列的第一个字符为根结点.对于中序遍历,根结点在中序遍历序 ...

  3. 给出中序和前序求后序Java,已知二叉樹前序,中序遍歷,求后序遍歷,java實現...

    簡單介紹一下思想,先看前序,前序遍歷的第一個節點,就是該樹的根.在中序中找到該根的位置,設為index,在中序遍歷集合中,位於index之前的屬於根的左子樹,位於index之后的屬於根的右子樹.然后, ...

  4. 二叉树面试题:前中序求后序、中后序求前序

    在面试时,避免不了的会遇到一些数据结构的面试题,今天我们就来了解一下二叉树的经典面试题: 已知二叉树的前序遍历顺序为ABDCEGHF,中序遍历顺序为DBAGEHCF,求该二叉树的后序遍历. 还有: 已 ...

  5. 已知一棵二叉树的中序序列和后序序列,写一个建立该二叉树的二叉链表存储结构的算法...

    已知一棵二叉树的中序序列和后序序列,写一个建立该二叉树的二叉链表存储结构的算法 #define N 10 //二叉树节点的个数 char postorderstr[]={};//后序序列 char i ...

  6. [算法] 已知前序和中序遍历,建立二叉树

    结点结构 typedef struct Node{char data;struct Node *left;struct Node *right; }Node; 已知前序和中序遍历顺序,建立二叉树 问题 ...

  7. 二叉树:已知先序和中序求后序,已知中序和后序求先序

    树的三种遍历方式的遍历顺序: 先序遍历:根.左子树.右子树(特点:第一个元素为根) 中序遍历:左子树.根.右子树(特点:根的两边分别为左子树和右子树) 后序遍历:左子树.右子树.根(特点:最后一个元素 ...

  8. C++实现已知二叉树前序遍历和中序遍历,求后序遍历

    C++实现已知二叉树前序遍历和中序遍历,求后序遍历 一.基本概念 1.先序遍历(NLR)可以确定二叉树的父子结点: 2.中序遍历(LNR)可以确定二叉树的左右子树: 3.后序遍历(LRN)可以确定二叉 ...

  9. PAT甲级1020变体:已知二叉树层序+中序序列,求后序遍历序列

    PAT甲级1020变体:已知二叉树层序+中序序列,求后序遍历序列 题目 输入格式 输出格式 输入样例 输出样例 代码 题目 已知二叉树层序+中序序列,求后序遍历序列. 输入格式 第一行给出该二叉树的节 ...

最新文章

  1. ubuntu下解决oracle sqlplus不能查看历史命令问题
  2. 最高效的回文数(C语言实现)
  3. JAVA 泛型中的通配符 T,E,K,V,?
  4. python如何提高工作效率_用Python的这3个优点,让工作效率提升一倍
  5. python如何创建txt_如何通过读取.txt文件为每个键创建包含多个“列表”的Python字典?...
  6. 数据库原理(一)—— 关系代数
  7. C/C++开发_C语言里类似C++的构造与析构
  8. ffmpeg CLI常用命令
  9. huffman树_Java使用哈夫曼树实现文件压缩的原理及实现
  10. conda可以更改环境的python anaconda替换环境的Python
  11. 中国 AI 天才养成计划:清华姚班和 100 个「张小龙」
  12. matlab中带脚咪头怎么找,咪头用万能表怎么测_咪头怎么辨认正负极
  13. 统计学 | 八大经典思想「AI核心算法」
  14. CSS基础 | (1) CSS是什么
  15. 新媒体下旅游目的地营销研究――以安徽省灵璧县为例
  16. Sulley fuzzer learning
  17. 线性泛函分析之对偶基
  18. Mysql8.0和Mysql5.0访问jdbc连接
  19. php查询替换_如何在PHP中使用正则表达式进行查找替换
  20. Axure电商后台业务管理系统原型模板+app电商原型交互+移动端电商通用PRD文档+全局交互用例说明+Axure高保真电商社交prd文档+电商prd+电商需求文档+订单、购物车、配货、物流、仓储

热门文章

  1. python的pandas重复值处理(duplicated()和drop_duplicates())
  2. BACnet协议读取与发送
  3. matlab 三维动态,matlab三维动态绘图
  4. 转行程序员需要做好哪些准备?只有这种人能成功转行ǃ
  5. 关于RC阻容复位电路的问题
  6. gsoc 任务_gsoc 2020与cern hsf暗物质和深度学习
  7. 【error】_smartbi数据集超出最大行数: DataRows > 1000
  8. 网络发现自动关闭不能启用、无法启用文件和打印共享的解决办法
  9. 笔记本固态盘数据丢失怎么办?笔记本固态盘怎么恢复数据
  10. window server2008下安装VS.NET2008