前言
还真是拿着好好的复习了下树形结构的各种遍历方法……好久没用过了,初看题看得头都大了
题目
原题链接:https://www.luogu.org/problemnew/show/P1030
题目描述
给出一棵二叉树的中序与后序排列。求出它的先序排列。(约定树结点用不同的大写字母表示,长度≤8 \le 8≤8)。
输入格式:
222行,均为大写字母组成的字符串,表示一棵二叉树的中序与后序排列。
输出格式:
111行,表示一棵二叉树的先序。
输入输出样例
输入样例#1:
BADC
BDCA
输出样例#1:
ABCD
思路
题目很直接了当了,就是已知树的中序遍历序列和后序遍历序列,求它的先序遍历序列,
根据树形结构的基础知识我们可以知道已知树的任意两种遍历序列即可确定一棵树。
那么,再看题,给出的已知条件是后序序列和中序序列,
我们知道,中序序列的父结点在中间,左右子树分布两边,
而后序序列父结点在后,左右子树在前面,
要求求出的先序序列的顺序则是父结点在前,左右子树在后;
根据这些,解题的方法就很简单明确了——首先直接访问后序序列的末尾,由后序序列的顺序我们可以知道,它即是根,然后再在中序序列中找到此节点,此时我们便可以在中序序列中得到它的左右子树,因为树是已确定的,那么在后序序列中与上法所得的左右子树等长的序列我们可以确定就是相应的左右子树的后序序列,
如此分割,反复的访问得到的后序序列的末尾元素,即可得到原树的先序序列了
代码
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.StringTokenizer;
public class Main {
static String naga = "",ushiro = "";
public static void dfs(String a,String b){
if(b.length()<1)
return;//无左右子树时终止
System.out.print(b.charAt(b.length()-1));//访问结点
int temp = a.indexOf(b.charAt(b.length()-1));//记录此次遍历的根结点在中序序列中的位置
dfs(a.substring(0,temp),b.substring(0,temp));//递归处理左子树
dfs(a.substring(temp+1,a.length()),b.substring(temp,b.length()-1));//递归处理右子树
}
public static void main(String[] args) {
Inputreader sc = new Inputreader();
while(sc.hasNext()){
naga = sc.next();
ushiro = sc.next();
dfs(naga,ushiro);
System.out.println();
}
}
}
class Inputreader
{
BufferedReader buf;
StringTokenizer tok;
Inputreader()
{
buf = new BufferedReader(new InputStreamReader(System.in));
}
boolean hasNext()
{
while(tok == null || !tok.hasMoreElements())
{
try
{
tok = new StringTokenizer(buf.readLine());
}
catch(Exception e)
{
return false;
}
}
return true;
}
String next()
{
if(hasNext()) return tok.nextToken();
return null;
}
int nextInt()
{
return Integer.parseInt(next());
}
long nextLong()
{
return Long.parseLong(next());
}
double nextDouble()
{
return Double.parseDouble(next());
}
BigInteger nextBigInteger()
{
return new BigInteger(next());
}
BigDecimal nextBigDecimal()
{
return new BigDecimal(next());
}
}