思路
为什么先序+中序,或者中序+后序可以创造一颗二叉树?
因为先序可以知道这颗树的根,后序也可以知道这颗树的根,那么再去看中序,中序的根就找到了,中序根左边的子树是左子树,中序根右边的是右子树,也就是说通过先序先确定根,然后中序找到根与左右子树,然后对左子树递归找根,对右子树递归找根,一直找不到为止
递归的思路是什么呢?
以先序+中序举例,先序先找到根,然后中序可以划分出左子树+根+右子树的形式,然后我们可以轻松拿到中序左子树的数组和中序右子树的数组,我们知道根据一个树的先序+中序可以很快在中序中确定根在哪,所以我们现在已经有了中序的左子树和右子树,并且他们都是按照中序的规则,那先序的根的左子树和右子树序列在哪呢?依然在原先序序列中找,既然我们已经在中序中找到了左子树和右子树序列,那么在先序中就很容易找出,因为要知道先序序列满足前面是根,中间一部分是左子树,最后一块是右子树的形式,中序满足最左边一块是左子树,中间根,右边右子树,后序的话左边是左子树,中间右子树,最后是根。
我们通过对中序的左子树递归找根,中序的右子树递归找根,一直到结点为 null 返回为止
Java 实现
// 结点
class Node {
int data;
Node left = null;
Node right = null;
}
// 二叉树
public class BinaryTree {
// 根结点
private Node root;
// 输入的数组
private int[] arr_in;
// 输出的数组
private int[] arr_out;
// 记录数组下标
private static int index;
// 初始化
public BinaryTree(int[] arr) {
root = new Node();
this.arr_in = arr;
arr_out = new int[arr.length];
index = 0;
}
// 根据先序遍历和中序遍历创建二叉树
public Node createByPreAndIn(int[] preArr, int[] inArr) {
if (preArr.length > 0) {
Node node = new Node();
node.data = preArr[0];
int i;
for (i = 0; preArr[0] != inArr[i]; i++) ;
// 中序左子树
int[] leftInArr = new int[i];
// 中序右子树
int[] rightInArr = new int[inArr.length - i - 1];
// 先序左子树
int[] leftPreArr = new int[i];
// 先序右子树
int[] rightPreArr = new int[inArr.length - i - 1];
System.arraycopy(inArr, 0, leftInArr, 0, leftInArr.length - 1);
System.arraycopy(inArr, i + 1, rightInArr, 0, rightInArr.length - 1);
System.arraycopy(preArr, 1, leftPreArr, 0, leftPreArr.length - 1);
System.arraycopy(preArr, i + 1, rightInArr, 0, rightPreArr.length - 1);
node.left = createByPreAndIn(leftPreArr, leftInArr);
node.right = createByPreAndIn(rightPreArr, rightInArr);
return node;
}
else
return null;
}
// 根据中序遍历和后序遍历创建二叉树
public Node createByInAndPost(int[] inArr, int[] postArr) {
if (inArr.length > 0) {
Node node = new Node();
node.data = postArr[postArr.length];
int i;
for (i = 0; postArr[postArr.length] != inArr[i]; i++) ;
// 中序左子树
int[] leftInArr = new int[i];
// 中序右子树
int[] rightInArr = new int[inArr.length - i - 1];
// 后序左子树
int[] leftPostArr = new int[i];
// 后序右子树
int[] rightPostArr = new int[inArr.length - i - 1];
System.arraycopy(inArr, 0, leftInArr, 0, leftInArr.length - 1);
System.arraycopy(inArr, i + 1, rightInArr, 0, rightInArr.length - 1);
System.arraycopy(postArr, 0, leftPostArr, 0, leftPostArr.length - 1);
System.arraycopy(postArr, i, rightPostArr, 0, rightPostArr.length - 1);
node.left = createByInAndPost(leftInArr, leftPostArr);
node.right = createByInAndPost(rightInArr, rightPostArr);
return node;
}
else
return null;
}