Java 由一维数组构建二叉树

二叉树:
中序遍历:[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() 方法,数组输入不在那么繁琐,而且运行耗时都有明显的下降!

  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值