二叉树:
中序遍历:[1,8,4,3,2,6]
一、一维数组构造二叉树
树节点TreeNode的数据结构
public class TreeNode {
Integer data;
TreeNode left;
TreeNode right;
//TreeNode parent;
TreeNode(){
}
public TreeNode(Integer data) {
this.data = data;
}
public TreeNode(Integer data, TreeNode left, TreeNode right) {
this.data = data;
this.left = left;
this.right = right;
}
}
主类结构
这里数组定义为Integer类型,而不是int类型,因为数组中存在null值。
Java为每个原始类型提供了封装类,Integer是java为int提供的封装类。
Integer的默认值为null,而int的默认值为0,即Integer可以区分出未赋值和值为0的区别,int则无法表达出未赋值的情况。
数组: Integer[] arr = new Integer[]{1,null,4,null,null,8,2,null,null,null,null,null,null,3,6};
public static void main(String[] args) {
Integer[] arr = new Integer[]{1,null,4,null,null,8,2,null,null,null,null,null,null,3,6};
//Integer[] arr = new Integer[]{1,null,4,8,2,null,null,3,6};
test(arr);
}
代码实现
第 i 个节点的左子节点为第 2*i 个节点,右子节点为第 2*i+1 个节点,因此用简单的递归就可以构建二叉树。
//一维数组构建二叉树
public TreeNode createBT(Integer[] arr, int i) // 初始时,传入的i==1
{
//TreeNode root = null; // 定义根节点
if (i > arr.length) {// i >= arr.length 时,表示已经到达了根节点
return null;
}
if(arr[i-1] == null){
return null;
}
TreeNode root = new TreeNode(arr[i-1]); // 根节点
root.left = createBT(arr, 2*i); // 递归建立左孩子结点
root.right = createBT(arr, 2*i+1); // 递归建立右孩子结点
return root;
}
但是这个方法对于一些情况却转化错误。因为这个一维数组是优化后的。
测试
public static void test(Integer[] input){
long begin = System.currentTimeMillis();
Solution solution = new Solution();
Solution.TreeNode root = solution.createBT(input,1); //根据数组(完全二叉树的层次遍历得到的数组)创建二叉树
List list = solution.inorderTraversal(root);
System.out.println("list = " + list);
long end = System.currentTimeMillis();
System.out.println();
System.out.println("耗时:" + (end - begin) + "ms");
System.out.println("-------------------");
}
结果
中序遍历结果:[1,8,4,3,2,6]
二、优化 createBT() 方法
主类
输入数组: Integer[] arr = new Integer[]{1,null,4,8,2,null,null,3,6};
数组比上面的方法的输入简洁了好多!
public static void main(String[] args) {
//Integer[] arr = new Integer[]{1,null,4,null,null,8,2,null,null,null,null,null,null,3,6};
Integer[] arr = new Integer[]{1,null,4,8,2,null,null,3,6};
test(arr);
}
代码实现
public TreeNode createBT(Integer[] arr){
if(arr.length == 0){
return null;
}
TreeNode root = new TreeNode(arr[0]);
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
boolean isLeft = true;//是左子树
for(int i = 1; i< arr.length; i++){
TreeNode node = queue.peek(); //peek()获取第一个元素,不移除
if(isLeft){
if(arr[i] != null){
node.left = new TreeNode(arr[i]);
queue.offer(node.left); //offer(E e) 在队列尾部添加一个元素,并返回是否成功
}
isLeft = false;
} else {
if(arr[i] != null){
node.right = new TreeNode(arr[i]);
queue.offer(node.right);
}
//右节点加入队列尾部,删除第一个元素,保证队列里保存的是根节点
queue.poll(); //poll() 删除队列中第一个元素,并返回该元素的值,
isLeft = true;
}
}
return root;
}
测试
public static void test(Integer[] input){
long begin = System.currentTimeMillis();
Solution solution = new Solution();
//Solution.TreeNode root = solution.createBT(input,1); //根据数组(完全二叉树的层次遍历得到的数组)创建二叉树
Solution.TreeNode root = solution.createBT(input);
List list = solution.inorderTraversal(root);
System.out.println("list = " + list);
long end = System.currentTimeMillis();
System.out.println();
System.out.println("耗时:" + (end - begin) + "ms");
System.out.println("-------------------");
}
结果
中序遍历结果:[1,8,4,3,2,6]
说明
优化后的 createBT() 方法,数组输入不在那么繁琐,而且运行耗时都有明显的下降!