JAVA中二叉树的常用算法

二叉树的遍历

  • 先序遍历

    • 递归方法

      public static void preOrder1(TreeNode root){
          if (root != null) {
              System.out.print(root.value+" ");
              preOrder1(root.left);
              preOrder1(root.right);
          }
      }
    • 非递归方法。使用栈结构,每次出栈后,按照先右后左的方式将子树入栈。

      public static void preOrder2(TreeNode root){
          if (root == null)
              return;
          LinkedList<TreeNode> stack = new LinkedList<TreeNode>();
          stack.push(root);
          while (!stack.isEmpty()){
              TreeNode tn = stack.pop();
              System.out.print(tn.value+" ");
              TreeNode left = tn.left;
              TreeNode right = tn.right;
              if (right != null)
                  stack.push(right);
              if (left != null)
                  stack.push(left);
          }
      }
  • 中序遍历

    • 递归方法

      public static void inOrder1(TreeNode root){
          if (root != null) {
              inOrder1(root.left);
              System.out.print(root.value+" ");
              inOrder1(root.right);
          }
      }
    • 非递归方法

      public static void inOrder2(TreeNode root) {
          if (root == null)
              return;
          LinkedList<TreeNode> stack = new LinkedList<TreeNode>();
          TreeNode cur = root;
          while (cur != null || !stack.isEmpty()) {//cur!=null为了保证第一次能进入循环
              if (cur == null){//当前节点为空要进行出栈操作,访问节点后再进入右子树
                  cur = stack.pop();
                  System.out.print(cur.value+" ");
                  cur = cur.right;
              } else {//一直从左子树入栈
                  stack.push(cur);
                  cur = cur.left;
              }
          }
      }
    public static void inOrder3(TreeNode root) {
        if (root == null)
            return;
        LinkedList<TreeNode> stack = new LinkedList<TreeNode>();
        TreeNode cur = root;
        while(cur !=null || !stack.isEmpty()) {
            while(cur != null) {//每次从当前节点的最左叶子节点开始访问,将遍历过的节点入栈
                stack.push(cur);
                cur = cur.left;
            }
            if (!stack.isEmpty()) {
                cur = stack.pop();
                System.out.print(cur.value+" ");
                cur = cur.right;//进入当前节点的右子树,用同样的方法访问
            }
        }
    }
  • 后序遍历

    • 递归方法

      //后序遍历
      public static void postOrder1(TreeNode root){
          if (root != null) {
              postOrder1(root.left);
              postOrder1(root.right);
              System.out.print(root.value+" ");
          }
      }
    • 非递归方法

      public static void postOrder2(TreeNode root) {
          LinkedList<TreeNode> stack = new LinkedList<TreeNode>();
          TreeNode last = null;//记录上一次访问节点
          TreeNode cur = root;
          while(cur != null || !stack.isEmpty()) {
              while (cur != null) {//找到当前节点的最左叶子节点
                  stack.push(cur);
                  cur = cur.left;
              }
              cur = stack.peekFirst();
              if (cur.right == null || cur.right == last) {//如果没有右子树或者右子树已经被访问过
                  cur = stack.pop();
                  last = cur;
                  System.out.print(cur.value+" ");
                  cur = null;//将当前节点置空,下次直接从栈中获取父节点信息
              } else {//右子树没有访问过,访问右子树
                  cur = cur.right;
              }
          }
      }
  • 层序遍历

    public static void leverTraverse(TreeNode root) {
        if (root == null)
            return;
        LinkedList<TreeNode> queue = new LinkedList<TreeNode>();
        queue.add(root);
        while (!queue.isEmpty()) {
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                TreeNode tn = queue.poll();
                System.out.print(tn.value+" ");
                TreeNode left = tn.left;
                TreeNode right = tn.right;
                if (left != null)
                    queue.add(left);
                if (right != null)
                    queue.add(right);
            }
        }
    }

判断是否完全二叉树

  • 完全二叉树:只有最下层节点的度可以小于2,并且最下面一层节点都集中在最左边。
  • 方法:层序遍历,若出现一个节点的子树为空,则后面节点的子树均必须为空。
  • 代码

    public static boolean isComplateTree(TreeNode root) {
        LinkedList<TreeNode> queue = new LinkedList<TreeNode>();
        boolean flag = true;
        queue.add(root);
        while (!queue.isEmpty()) {
            TreeNode tn = queue.poll();
            TreeNode left = tn.left;
            TreeNode right = tn.right;
            if (flag) {
                if (left == null)
                    flag = false;
                else
                    queue.add(left);
            } else {
                if (left != null)
                    return false;
            }
            if (flag) {
                if (right == null)
                    flag = false;
                else
                    queue.add(right);
            } else {
                if (right != null)
                    return false;
            }
        }
        return true;
    }
    

判断是否同一棵树

  • 代码

    public static boolean compareTree(TreeNode root1, TreeNode root2) {
        if ((root1 == null && root2 != null) || (root1 != null && root2 == null))
            return false;
        else if (root1 == null && root2 == null)
            return true;
        if (root1.value == root2.value) {
            return compareTree(root1.left, root2.left) && compareTree(root1.right, root2.right);
        } else {
            return false;
        }
    }

判断是否二叉排序树

  • 方法:中序遍历的方法,保存上一次访问节点的值。
  • 代码

    static int pre = Integer.MIN_VALUE;
    //判断是否二叉排序树
    public static boolean isBST(TreeNode root) {
        if (root == null)
            return true;
        if (isBST(root.left)) {
            if (pre < root.value) {
                pre = root.value;
                return isBST(root.right);
            } else
                return false;
        } else
            return false;
    }

是否平衡二叉树

  • 方法:后序遍历,保证两颗子树高度差不超过1
  • 代码

    //是否平衡二叉树,小于0表示不是
    public static int isBalanced(TreeNode root) {
        if (root == null)
            return 0;
        int lh = isBalanced(root.left);
        int rh = isBalanced(root.right);
        if (Math.abs(lh-rh) <= 1) {
            return Math.max(lh, rh)+1;
        } else
            return -1;
    }

查找最近公共祖先节点

  • 方法:递归。
    结束条件:root为其中一个节点或者root为null,返回root
    分别对左右子树递归查找
    左子树查找返回值为null,则两个节点肯定都在右子树上,公共祖先节点即为右递归的返回值;若左子树查找返回值不为null,判断右子树查找返回值,若为null,说明两个节点都在左子树上,公共祖先节点即为左递归返回值,若两个都不为null,则root即为公共祖先节点。
  • 代码

    //查找最近公共祖先节点
    public static TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if (root == null || root == p || root == q)
            return root;
        TreeNode left = lowestCommonAncestor(root.left, p, q);
        TreeNode right = lowestCommonAncestor(root.right, p, q);
        return left == null ? right : right == null ? left : root;
    }

构造树

  • 已知先序和中序

    public static TreeNode constructPreAndIn(int[] preOrder, int[] inOrder) {
        if (preOrder==null || inOrder == null || preOrder.length != inOrder.length)
            return null;
        return constructPreAndIn(preOrder, 0, preOrder.length-1, inOrder, 0, inOrder.length-1);
    }
    public static TreeNode constructPreAndIn(int[] preOrder, int pl, int pr, int[] inOrder, int il, int ir){
        if (pl > pr){
            return null;
        }
        TreeNode root = new TreeNode(preOrder[pl]);
        int pos = il;
        for (; pos <= ir; pos++) {
            if (inOrder[pos] == root.value)
                break;
        }
        root.left = constructPreAndIn(preOrder, pl+1, pl+pos-il, inOrder, il, pos-1);
        root.right = constructPreAndIn(preOrder, pl+pos-il+1, pr, inOrder, pos+1, ir);
        return root;
    }
  • 已知后序和中序

    public static TreeNode constructPostAndIn(int[] postOrder, int[] inOrder) {
        if (postOrder==null || inOrder == null || postOrder.length != inOrder.length)
            return null;
        return constructPostAndIn(postOrder, 0, postOrder.length-1, inOrder, 0, inOrder.length-1);
    }
    public static TreeNode constructPostAndIn(int[] postOrder, int pl, int pr, int[] inOrder, int il, int ir){
        if (pl > pr){
            return null;
        }
        TreeNode root = new TreeNode(postOrder[pr]);
        int pos = il;
        for (; pos <= ir; pos++) {
            if (inOrder[pos] == root.value)
                break;
        }
        root.left = constructPostAndIn(postOrder, pl, pl+pos-il-1, inOrder, il, pos-1);
        root.right = constructPostAndIn(postOrder, pr-(ir-pos), pr-1, inOrder, pos+1, ir);
        return root;
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值