复原二叉树 题解

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

以上是关于复原二叉树 题解的主要内容,如果未能解决你的问题,请参考以下文章

二叉树复原

二叉树 基础题解

二叉树 基础题解

二叉树遍历-力扣题解

剑指 Offer 27. 二叉树的镜像 题解

leetCode题解之反转二叉树