注意:不能用普通的前序遍历创建,要用带空结点的前序遍历创建二叉树。
如:preOrder=ABC#D###E,创建的二叉树形态为:
思路:根据前序遍历,很容易找到根的值。(下标为0的位置处)。因此每次创建左子树时,传的是原数组长度-1(从原数组下标-1处开始);创建右子树时,应该使用原数组长度-1-左子树创建时所用的个数。因此创建一棵树应该返回两个值,一个是根结点,一个是创建过程中使用的结点数。那么怎么让一个函数返回两个值呢?用类来解决。终止条件:数组为null,返回(null,0)。我们使用'#‘来表示数组中的空结点的值,特殊情况:如果遇到根结点值为'#',空结点没有子树,因此直接返回(null,1)。
具体步骤:
1.先判断是否是终止条件。是,则返回(null,0);不是,继续下一步。
2.然后取根结点的值,就是preOrder[0]的值。
3.判断是否是特殊情况(空结点)。是,则直接返回(null,1)。如果不是,则创建根结点,执行第4步。
4.递归创建根结点的左子树。利用preOrder,找到左子树的前序遍历数组,去掉第一个值。这里传数组,我们使用数组拷贝去实现。Arrays.copyOfRange(原数组名,起始索引,最终索引),复制的数组不包括最后索引的元素。对于左子树,就是Arrays.copyOfRange(preOrder,1,preOrder.length).
5.递归创建根结点的右子树。利用preOrder,找到右子树的前序遍历数组,去掉第一个值,去掉左子树使用的值。Arrays.copyOfRange(preOrder,1+left.used,preOrder.length).其中,left为创建左子树时返回的类。
6.将根、左子树和右子树关联起来。root.left=left.root;root.right=right.root;
7.返回创建好的树和使用的结点数。
使用到的类有:
//结点类
public static class Node{
char val;//值
Node left;//左子树
Node right;//右子树
Node(char val){
this.val=val;
}
}
//返回值类
class CreateTreeResult{
public TreeMethod.Node root;
public int used;
public CreateTreeResult(TreeMethod.Node root, int used) {
this.root = root;
this.used = used;
}
}
完整代码:
package com.xunpu.datastruct.tree;
import java.util.Arrays;
class CreateTreeResult{
public TreeMethod.Node root;
public int used;
public CreateTreeResult(TreeMethod.Node root, int used) {
this.root = root;
this.used = used;
}
}
public class TreeMethod {
private static int count=0;
public static class Node{
char val;//值
Node left;//左子树
Node right;//右子树
Node(char val){
this.val=val;
}
}
//创建树
static CreateTreeResult createTree(char[] preOrder){
//1.判断是否是终止条件
if(preOrder.length==0){//终止条件 E或E##
return new CreateTreeResult(null,0);
}
//2.获取根结点的值
char rootValue=preOrder[0];
//3.判断是否为空结点
if(rootValue=='#'){
return new CreateTreeResult(null,1);
}
//创建根结点
Node root=new Node(rootValue);
//4.创建左子树 利用递归
char[] leftPreorder=new char[preOrder.length-1];
leftPreorder= Arrays.copyOfRange(preOrder,1,preOrder.length);
CreateTreeResult left=createTree(leftPreorder);
// left.used;//左子树创建过程中使用的个数
// 右子树使用的个数为preOrder.length-1-left.used
//5.创建右子树 利用递归
char[] rightPreorder=new char[preOrder.length-1-left.used];
rightPreorder= Arrays.copyOfRange(preOrder,1+left.used,preOrder.length);
CreateTreeResult right=createTree(rightPreorder);
//6.将根、左子树和右子树关联起来
root.left=left.root;
root.right=right.root;
//7.返回树和使用的结点树
return new CreateTreeResult(root,1+left.used+right.used);
}
public static void main(String[] args) {
char[] array=new char[]{'A','B','C','#','D','#','#','#','E'};
CreateTreeResult result=createTree(array);
System.out.println(result.used);
System.out.println(result.root.left.left.right.val);
System.out.println(result.root.right.val);
}
}