有这么一道面试题:已知一棵二叉树的前序遍历结果为ABCDEFGHI,中序遍历结果为CBDEAFHGI,则后序遍历的结果为( )。
这个题目很简单,很多应聘者都知道结果,而且也能够分析他的思路,但要求写代码却有不少人写不出来。
思路大家都知道:前序遍历列表的第一个点,是树的根节点;它在中序遍历列表的位置,把中序遍历列表分为左右两截,左边为左子树,右边为右子树。然后,再分别对左右子树进行同样的操作,这样就可以把整棵树给构造出来,然后对树进行后序遍历。
最简单的方法,当然就是用递归了,代码如下:
import java.util.List;
import java.util.function.Consumer;
import javax.annotation.Nullable;
import com.google.common.collect.Lists;
/**
* 已知前序遍历和中序遍历,求后序遍历
*
* @author liuwenzhe2008@qq.com
*
*/
public class Tree<T> {
private final T value;
@Nullable private Tree<T> left;
@Nullable private Tree<T> right;
public Tree(T value) {
this.value = value;
}
/**
* 解析前序遍历和中序遍历,创建树并返回根节点
* <p>
* @param preorder 前序遍历输入
* @param inorder 中序遍历输入
* @return 创建出来的树
*/
@Nullable
public static <T> Tree<T> from(List<T> preorder, List<T> inorder) {
// 参数检测:必须一样长
if (preorder.size() != inorder.size()) {
throw new IllegalArgumentException("Preorder and Inorder should have the same size.");
}
// 没有元素的情况
if (preorder.isEmpty()) {
return null;
}
// 找出前序遍历列表里第一个元素在中序遍历列表的位置,
T first = preorder.get(0);
int index = inorder.indexOf(first);
// 把中序遍历列表分成左右两截,
List<T> mdLeft = inorder.subList(0, index);
List<T> mdRight = inorder.subList(index + 1, inorder.size());
// 分别跟前序遍历列表对应,确保长度相同
List<T> fwLeft = preorder.subList(1, 1 + mdLeft.size());
List<T> fwRight = preorder.subList(preorder.size() - mdRight.size(), preorder.size());
// 以前序遍历的第一个元素作为根节点构造一棵树
Tree<T> root = new Tree<>(first);
// 递归构造左子树和右子树
root.left = from(fwLeft, mdLeft);
root.right = from(fwRight, mdRight);
return root;
}
@Nullable
public static Tree<Character> from(String preorder, String middle) {
return from(Lists.charactersOf(preorder), Lists.charactersOf(middle));
}
/**
* 后序遍历,提供回调onVisit
*/
public void postorder(Consumer<T> onVisit) {
// 遍历左子树
if (left != null) {
left.postorder(onVisit);
}
// 遍历右子树
if (right != null) {
right.postorder(onVisit);
}
// 访问根节点
onVisit.accept(value);
}
/**
* 测试:输入前序遍历列表和中序遍历列表,打印后序遍历列表
*/
public static void main(String[] args) {
Tree.from("ABCDEFGHI", "CBDEAFHGI").postorder(System.out::print); // print "CEDBHIGFA";
}
}
——- 本博客所有内容均为原创,转载请注明作者和出处 ——-
作者:刘文哲
联系方式:liuwenzhe2008@qq.com