复原二叉树 题解
Posted eleven-qian-shan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了复原二叉树 题解相关的知识,希望对你有一定的参考价值。
复原二叉树
http://codeup.cn/problem.php?cid=100000611&pid=0
题目简述:
给你一棵二叉树的前序遍历和中序遍历,要求输出这棵二叉树的后序遍历
输入无限组,没有停止要求(文件读入)
补充知识:
既然做到了这道题,那就补充一下关于还原二叉树及二叉树遍历的知识,如下:
- 二叉树遍历
1.前序遍历:按照“根、左、右”的顺序遍历一棵树
2.中序遍历:按照“左、根、右”的顺序遍历一棵树
3.后序遍历:按照“左、右、根”的顺序遍历一棵树
4.层序遍历:按层从根节点开始由上至下,每一层由左至右的顺序遍历一棵树
(层序遍历相当于对二叉树从根节点开始的BFS广度优先搜索)
- 根据遍历还原二叉树
1.知道前序和中序,树是唯一的。具体还原步骤如下:
(1)前序遍历的第一位是这棵树的Root(根节点)
(2)在中序遍历中找到Root的位置为index,在Root左边的即为Root的左子树,右边的则是右子树(特别的,如果没有元素在左边或右边,则说明该节点没有左子树或右子树)
(3)再在前序遍历中找到Root的下一位,即为Root左子树的根节点root(注意一下区别)
(4)然后像Root一样在中序中找到root的位置,在root左边的即为root的左子树,右边的则是右子树
(5)不断重复以上操作(其实重复1、2即可),一棵树就复原出来了
2.知道中序和后序,树是唯一的。具体步骤如下:
(1)因为后序是最后访问根,所以后序的最后一个节点是这棵树的Root
(后序处理其实可以看做将前序倒过来了。注意:只是操作像倒过来,并不是说前序反转就是后序!)
(2)在中序中找到Root的位置,以此划分左右子树
(3)然后重复1、2步骤,迭代递归求解即可复原树
3.知道前序和后序,树不是唯一的。原因如下:
前序和后序在本质上都是将父节点与子节点进行分离,但并没有指明左子树和右子树的能力,因此得到这两个序列只能明确父子节点关系,而不能确定一棵二叉树。
来一波文字+图帮助大家理解qvq(以题目第二个输入为例)
总结一下:
知道前序中序或后序中序,可以复原唯一的树;而只知道前序和后序只能明确父子节点关系。
原理:前序或后序可以确立每一个子树的root,而中序则可以划分左右子树,然后迭代就可以复原一棵树
提示:
知道了原理,不妨自己先试着编一下代码,这样有助于理解下面给出的代码,也更能找出自己的错误qwq
代码Code:
因为这是模板题,所以思路就是如上补充的知识(如果不是很懂,可以根据下面代码进行理解,自认为很详细)
代码如下:
#include <bits/stdc++.h>
using namespace std;
char pre[100001];
char in[100001];
struct node {
char data; //数据域
node *lc; //指向左子树根节点的指针
node *rc; //指向右子树根节点的指针
};
inline void build(node * &t,int prel,int prer,int inl,int inr) {
if(prel>prer) { //前序序列长度小于等于0时,直接返回
t=NULL;
return ;
}
t=new node(); //申请一个node型变量的地址空间,用来存放当前二叉树的根节点
t->data=pre[prel]; //节点权值为pre[prel]
int index;
for(index=inl;index<=inr;index++) {
if(in[index]==pre[prel]) break; //在中序序列中找到当前的根节点位置,存在index中
}
int numl=index-inl; //左子树的节点个数
build(t->lc,prel+1,prel+numl,inl,index-1); //分别递归左右子树
build(t->rc,prel+numl+1,prer,index+1,inr);
}
inline void postorder(const node *t) {
if(t==NULL) return ; //到达空树,递归边界
postorder(t->lc); //访问左子树
postorder(t->rc); //访问右子树
printf("%c",t->data);
}
int main() {
while(cin>>pre>>in) { //连续输入
node *root=NULL; //新建空根节点root
build(root,0,strlen(pre)-1,0,strlen(pre)-1); //开始复原二叉树
postorder(root); //根据复原的二叉树输出后序遍历
puts("");
memset(pre,‘0‘,sizeof(pre)); //清空好习惯qwq
memset(in,‘0‘,sizeof(in));
}
return 0;
}
以上是关于复原二叉树 题解的主要内容,如果未能解决你的问题,请参考以下文章