(此系列试题来源于Java面试宝典书籍)
一、选择题
1. 已知一颗二叉树,如果先序遍历的节点顺序是:ADCEFGHB,中序遍历是:CDFEGHAB,则后序遍历结果为:
- A. CFHGEBDA
- B. CDFEGHBA
- C. FGHCDEBA
- D. CFHGEDBA
解析:
二叉树
- 前序遍历:根结点 左子树 右子树
- 中序遍历:左子树 根节点 右子树
- 后序遍历:右子树 根节点 左子树
思路:
- 根据前序遍历可以知道根节点
- 通过根节点将中序遍历分为两截进行递归操作
public class BinaryTree {
static class Node{
String value;
Node leftTree;
Node rightTree;
public Node(String value, Node leftTree, Node rightTree) {
this.value = value;
this.leftTree = leftTree;
this.rightTree = rightTree;
}
void printValue(){
System.out.println(value);
}
}
public static Node createNode(String value){
return new Node(value,null,null);
}
public static Node createNode(char value){
return createNode(String.valueOf(value));
}
/**
* 添加节点到左子树
*/
public static void addNodeToLeft(Node root,Node child){
if (root.leftTree == null){
root.leftTree = child;
}else {
throw new RuntimeException("the left child has already created");
}
}
/**
* 添加节点到右子树
*/
public static void addNodeToRight(Node root, Node child) {
if (root.rightTree == null) {
root.rightTree = child;
} else {
throw new RuntimeException("the right child has already created");
}
}
/**
* 前序遍历
*/
public static void preShow(Node root){
root.printValue();
if (root.leftTree != null){
preShow(root.leftTree);
}
if (root.rightTree != null){
preShow(root.rightTree);
}
}
/**
* 中序遍历
*/
public static void midShow(Node root){
if (root.leftTree != null){
midShow(root.leftTree);
}
root.printValue();
if (root.rightTree != null){
midShow(root.rightTree);
}
}
/**
* 后序遍历
*/
public static void postShow(Node root){
if (root.leftTree != null){
postShow(root.leftTree);
}
if (root.rightTree != null){
postShow(root.rightTree);
}
root.printValue();
}
/**
* 根据前序和中序遍历,推断后序遍历
*/
public static Node createTreeByPreAndMid(Node root,String pre_values,String mid_values){
if (!"".equals(mid_values)){
// 同步先序和中序字符串
String new_pre_values = synchronizedPreAndMid(pre_values,mid_values);
//这样可以保证,先序的第一个肯定是这棵树的根节点
char rootValue = new_pre_values.charAt(0);
root = createNode(rootValue);
int rootIndexOfIn = mid_values.indexOf(rootValue);//得到根节点在中序中的位置
// 根节点左边的一大串
String leftMidValues = mid_values.substring(0,rootIndexOfIn);
// 根节点右边的一大串
String rightMidValues = mid_values.substring(rootIndexOfIn+1,mid_values.length());
// 如果左边一大串就剩下一个了,
// 说明这肯定就是这课树的左节点,如果还剩下多个就继续递归调用
if(leftMidValues.length() == 1){
addNodeToLeft(root, createNode(leftMidValues));
}else if(leftMidValues.length() != 0){
addNodeToLeft(root, createTreeByPreAndMid(root, new_pre_values, leftMidValues));
}
// 如果右边一大串就剩下一个了,
// 说明这肯定就是这课树的右节点,如果还剩下多个就继续递归调用
if(rightMidValues.length() == 1){
addNodeToRight(root, createNode(rightMidValues));
}else if(rightMidValues.length() != 0){
addNodeToRight(root, createTreeByPreAndMid(root, new_pre_values, rightMidValues));
}
}
return root;
}
/**
* 每次都把在pre_values但是不在in_values里面的元素删掉,但是顺序不要变
*/
private static String synchronizedPreAndMid(String preValues, String midValues) {
String retVal = "";
for (int i = 0; i < preValues.length(); i++) {