题目描述
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
解题思路
- 在中序遍历序列中元素左边的元素在该元素的左子树上,右边的元素在右子树上,在根据前序遍历序列,就上面的示例可以得到:2为1的左节点,4为2的左节点;
- 右节点的确定:在前序遍历中,父节点先于右节点出现,在中序遍历中,父节点与右节点中间的节点是右节点的左节点。而这部分节点在前序遍历中位于该节点的左边。所以某个右节点的父节点在中序遍历的顺序中是最近的,先于此节点出现,且在前序遍历顺序中也先于此节点出现:所以3为1的右节点
- 树的中非递归中序遍历和后序遍历参考:
https://www.cnblogs.com/llhthinker/p/4747962.html
源码实现
import java.util.HashMap;
import java.util.Scanner;
import java.util.Stack;
public class FirstDay {
public static void main(String[] args){
Scanner in=new Scanner(System.in);
int Size=in.nextInt();
int[] pre=new int[Size];
int[] ints=new int[Size];
for(int i=0;i<Size;i++){
pre[i]=in.nextInt();
}
for(int i=0;i<Size;i++){
ints[i]=in.nextInt();
}
TreeNode treeNode=reConstructBinaryTree(pre,ints);
// InorderTraversal(treeNode);
PostorderTraversal(treeNode);
}
public static void PostorderTraversal(TreeNode treeNode){
Stack<TreeNode> firststack=new Stack();
Stack<TreeNode> secondstack=new Stack();
TreeNode parent=treeNode;
firststack.push(parent);
secondstack.push(parent);
while (!firststack.isEmpty()){
if(parent.right!=null){
parent=parent.right;
firststack.push(parent);
secondstack.push(parent);
}else {
while(!firststack.isEmpty()){
parent=firststack.pop();
if(parent.left!=null){
parent=parent.left;
firststack.push(parent);
secondstack.push(parent);
break;
}
}
}
}
while(!secondstack.isEmpty()){
parent=secondstack.pop();
System.out.println(parent.val);
}
}
public static void InorderTraversal(TreeNode treeNode){
Stack<TreeNode> stack=new Stack();
TreeNode parent=treeNode;
stack.push(parent);
while (!stack.isEmpty()){
if(parent.left!=null){
stack.push(parent.left);
parent=parent.left;
}else {
while (!stack.isEmpty()) {
parent = stack.pop();
System.out.println(parent.val);
if (parent.right != null) {
parent = parent.right;
stack.push(parent);
break;
}
}
}
}
}
static class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
/**
* 生成二叉树
* @param pre 前序遍历序列
* @param in 后序遍历序列
* @return 二叉树的根节点
*/
public static TreeNode reConstructBinaryTree(int [] pre,int [] in) {
TreeNode treeNode=new TreeNode(pre[0]);
Stack<TreeNode> stack=new Stack();
stack.push(treeNode);
TreeNode parent=treeNode;
HashMap<Integer,Integer> map=new HashMap<>();
HashMap<Integer,Boolean> Mark=new HashMap<>();
iniMap(map,Mark,in);
Mark.put(pre[0],true);
for(int i=1;i<pre.length;i++){
Mark.put(pre[i],true);
TreeNode Node=new TreeNode(pre[i]);
if(isLeft(parent.val,pre[i],in)) {
parent.left = Node;
parent=Node;
stack.push(parent);
}else{
int loca=map.get(pre[i]);
int num=-1;
for(int j=loca-1;j>=0;j--){
if(Mark.get(in[j])) {
num = j;
break;
}
}
while(num!=-1&&!stack.isEmpty()){
TreeNode tnode=stack.pop();
if(tnode.val==in[num]) {
tnode.right = Node;
parent=Node;
stack.push(Node);
break;
}
}
}
}
return treeNode;
}
/**
* 判断FirstNum在in中的位置是否在SecondNum的左边
* @param FirstNum
* @param SecondNum
* @param in
* @return
*/
public static boolean isLeft(int FirstNum,int SecondNum,int[] in){
boolean Mark=false;
for(int i=0;i<in.length;i++){
if(in[i]==SecondNum)
Mark=true;
if(in[i]==FirstNum){
if(Mark)
return true;
else
return false;
}
}
return false;
}
/**
* 将in中的数字与位置相匹配
* @param map key=in中的数字,value=该数字在in中的位置
* @param in
*/
public static void iniMap(HashMap<Integer,Integer> map,HashMap<Integer,Boolean> Mark,int[] in){
for(int i=0;i<in.length;i++){
map.put(in[i],i);
Mark.put(in[i],false);
}
}
}