参考了柳婼思路,在此感谢柳神。
她的是用C++写成的:传送门
自己是用Java写的。
java中的TreeMap函数可以根据键自动正序排序的,这个跟C++中的Map异曲同工之妙。
import java.util.TreeMap;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
static int[] InOrder;
static int[] PostOrder;
static BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
static TreeMap<Integer,Integer> preOrder = new TreeMap<>();//这是先序遍历的顺序,键是从0开始的,按照队列(也就是层次遍历顺序)标记的叶子序号,值则是对应这个叶子输入的对应值。()
public static void main(String[] args) {
int[] num =readLine();
PostOrder = readLine();
InOrder = readLine();
pre(num[0]-1,0,num[0]-1,0);
int time = 0;
for(Integer val: preOrder.values()) {
System.out.print(val);
time++;
if(time < preOrder.values().size()) {
System.out.print(" ");
}
}
}
public static void pre(int root,int start,int end,int index) {
//root是后序中 当前树的根
//start是中序中 树的起点
//end是中序中 树的结束点
/*
* 1.递归结束的条件是发现结束点在开始点之后
*/
if(end < start) {
return;
}
int i = start;
while(i < end && InOrder[i] != PostOrder[root])i++;//i为中序中当前树根的下标
preOrder.put(index, PostOrder[root]);
/*
* 2.开始递归
* 左子树递归
* 左子树的根求法 是 root(当前树的的后序节点序号)-右子树的个数-1=左子树在后序遍历中最后一个元素(也就是左子树的根)
* 而右子树的个数,可以通过 中序中 end-root+1 求出。
* 相当于 root- (end - i ) -1 = root+i - end -1
*
* start(左子树在中序中的起始点)是 start
* end(左子树在中序中的结束点)是 i-1 (i为中序中当前树根的下标)
* 左子树:(2*root-end-2,start,i-1)
*
* 右子树的根:root-1
* start(右子树在中序中的起始点)是 i + 1
* end(右子树在中序中的结束点)是 end (i为中序中当前树根的下标)
*/
pre(root-end+i-1,start,i-1,index*2+1);//左子树递归。
//在完全二叉树中,当根的下标从0开始时,它的左孩子下标是2*index+1
pre(root-1,i+1,end,index*2+2);//右子树递归
//在完全二叉树中,当根的下标从0开始时,它的左孩子下标是2*index+2
//这个规律可以自己画图验证
}
public static int[] readLine() {//封装了输入函数,使用BfferedReader效率高于Scanner
String str = null;
try {
str = bf.readLine();
}catch(IOException e){
e.printStackTrace();
}
String[] strs = str.split(" ");
int[] ints = new int[strs.length];
for(int i = 0;i < ints.length;i++) {
ints[i] = Integer.parseInt(strs[i]);
}
return ints;
}
}