Java 二叉树常见算法总结

递归遍历

前序遍历

public void preOrder(TreeNode node){
        if (node != null){
            System.out.println(node.data);
            preOrder(node.leftNode);
            preOrder(node.RightNode);
        }
    }

中序遍历

public void midOrder(TreeNode node){
        if (node != null){
            midOrder(node.leftNode);
            System.out.println(node.data);
            midOrder(node.RightNode);
        }
    }

后序遍历

public void posOrder(TreeNode node){
        if (node != null){
            posOrder(node.leftNode);
            posOrder(node.RightNode);
            System.out.println(node.data);
        }
    }

非递归遍历

前序遍历

public void preOrder1(TreeNode node){
        Stack<TreeNode> stack = new Stack<>();
        while (node != null || !stack.empty()){
            while (node != null){
                System.out.println(node.data);
                stack.push(node);
                node = node.leftNode;
            }
            if (!stack.empty()){
                node = stack.pop();
                node = node.RightNode;
            }
        }
    }

中序遍历

public void midOrder1(TreeNode node){
 
        Stack<TreeNode> stack = new Stack<>();
        while ( node != null || !stack.empty()){
            while ( node != null){
                stack.push(node);
                node = node.leftNode;
            }
            if (!stack.empty()){
                node = stack.pop();
                System.out.println(node.data);
                node = node.RightNode;
            }
        }
    }

后序遍历

方法1public void posOrder1(TreeNode node){
        Stack<TreeNode> stack1 = new Stack<>();
        Stack<Integer> stack2 = new Stack<>();
        while (node != null || !stack1.empty()){
            while ( node != null){
                stack1.push(node);
                stack2.push(0);
                node = node.leftNode;
            }
            while (!stack1.empty() && stack2.peek() == 1){
                stack2.pop();
                System.out.println(stack1.pop().data);
            }
            if (!stack1.empty()){
                stack2.pop();
                stack2.push(1);
                node = stack1.peek();
                node = node.RightNode;
            }
        }
    }

方法2/**
     * 后序遍历(非递归)
     * 前序遍历  根--左--右
     * 后序遍历  左--右--根
     * 借用前序遍历算法思想 修改成 根--右--左,然后反转得到  左--右--根
     * @param node
     * @return
     */
    public ArrayList<Integer> posOrder2(TreeNode node){
        ArrayList<Integer> list = new ArrayList<>();
        if (node != null){
            Stack<TreeNode> stack = new Stack<>();
            stack.push(node);
            while (!stack.empty()){
                TreeNode node1 = stack.pop();
                list.add(node1.data);
                if (node1.leftNode != null) stack.push(node1.leftNode);
                if (node1.RightNode != null)stack.push(node1.RightNode);
            }
            Collections.reverse(list);
        }
        return list;
    }

层序遍历

public void levelOrder1(TreeNode node){
 
        if (node == null) return;
        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(node);
        TreeNode node1;
        while (!queue.isEmpty()){
            node1 = queue.poll();
            System.out.println(node1.data);
            if (node1.leftNode != null)queue.offer(node1.leftNode);
            if (node1.RightNode != null)queue.offer(node1.RightNode);
        }
    }

常见应用

二叉树的最大深度

public int depth(TreeNode node){
        if (node == null) return 0;
        int l = depth(node.leftNode);
        int r = depth(node.RightNode);
        if (l > r) return l + 1;
        else return r + 1;
    }

最小深度

 给定一个二叉树,找出其最小深度。

 二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
 
 说明: 叶子节点是指没有子节点的节点。
 
 示例:
 给定二叉树 [3,9,20,null,null,15,7]3
     \
     20
     /  
    15   
 返回它的最大深度 2,而不是0。


注意:要注意到只有一个子节点的情况,因为最小深度是根节点到最近叶子节点的过程中节点的个数

 
public int mindepth(TreeNode root) {
       if(root == null)
           return 0;
       //不是叶子节点有三种情况,左右节点不为空,左节点为空右节点不为空,左节点不为空右节点为空
       if(root.left !=null && root.right!=null) // 两个节点都不为空
           return Math.min(mindepth(root.left),mindepth(root.right))+1;
       else if(root.left !=null)	// 右节点为空
           return mindepth(root.left)+1;
       else
           return mindepth(root.right)+1;	// 左节点为空
   }

注意:不能直接如下写,因为深度到达的节点必须是叶子节点

public int mindepth(TreeNode root) {
       if(root == null)
           return 0;
       return Math.min(mindepth(root.left),mindepth(root.right))+1;
}

复制二叉树

 public static TreeNode cloneTree(TreeNode root){
        TreeNode node=null;
        if(root==null) return null;
        node = new TreeNode(root.data);
        node.leftNode = cloneTree(root.leftNode);
        node.RightNode = cloneTree(root.RightNode);
        return node;
    }

二叉树节点个数

//返回左子树和右子树个数的和,然后加上一个根节点
public int sumNode(Node node){
		if(node==null){
			return 0;
		}else{
			int a=sumNode(node.getLeftChild());
			int b=sumNode(node.getRightChild());
			return 1+a+b;
		}
	}

二叉树叶子节点个数

int count=0; 
public void getCountLeaf(TreeNode root) {
        if(root == null) {
            return;
        }
        if(root.left == null && root.right == null) {
            count++;
        }
        getCountLeaf(root.left);
        getCountLeaf(root.right);
    }

二叉树中第K层节点的个数

public void leveOrder(TreeNode node,int level){
 
        if (node == null || level < 1)return;
        if ( level == 1){
            System.out.println(node.data);
            return;
        }
        leveOrder(node.leftNode,level - 1);
        leveOrder(node.RightNode,level - 1);
    }

销毁二叉树

BiTree DestroyBiTree(BiTree T) {
    if (T != null) {
        //销毁左子树
        if (T.lchild != null) {
            T.lchild = DestroyBiTree(T.lchild);
        }
        //销毁右子树
        if (T.rchild != null) {
            T.rchild = DestroyBiTree(T.rchild);
        }
        //销毁当前节点
        T = null;
    }
    return T;
}

反转二叉树或二叉树的镜像

  • 先序遍历
  • 从上到下反转
public void Mirror(TreeNode root) {
        if(root == null) {
            return;
        }
        if((root.leftNode == null) && (root.RightNode == null)) {
            return;
        }
        TreeNode temp = root.leftNode;
        root.leftNode = root.RightNode;
        root.RightNode = temp;
        Mirror(root.leftNode);
        Mirror(root.RightNode);
    }

两棵二叉树是否互为镜像

  • 先序遍历
  • 先比较根节点,树1的左子树和树2的右子树比较,树1的右子树和树2的左子树比较
   public boolean isMirror(TreeNode t1,TreeNode t2){
        if(t1==null&&t2==null){
            return true;
        }
        if(t1==null||t2==null){
            return false;
        }
        if(t1.val != t2.val){
            return false;
        }
        return isMirror(t1.left,t2.right)&&isMirror(t1.right,t2.left);
        
    }

判断某个二叉树是否对称

public boolean isSymmetric(TreeNode root) {
		// 树为空,则返回true
		if (root == null)
			return true;
		else
			return isMirror(root.left, root.right);
	}

public boolean isMirror(TreeNode t1,TreeNode t2){
        if(t1==null&&t2==null){
            return true;
        }
        if(t1==null||t2==null){
            return false;
        }
        if(t1.val != t2.val){
            return false;
        }
        return isMirror(t1.left,t2.right)&&isMirror(t1.right,t2.left);
        
}
 

二叉树中和为某一值的路径

(路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径)

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    List<List<Integer>> res=new ArrayList<>();
    List<Integer> temp=new ArrayList<>();
    public List<List<Integer>> pathSum(TreeNode root, int sum) {

        findPath(root,sum);
        return res;

    }

    public void findPath(TreeNode root,int sum){
        if(root!=null){
    //加入当前节点的值
            temp.add(root.val);
            if(root.left==null&&root.right==null&&(sum-root.val==0)){
                res.add(new ArrayList(temp));
            }
            //temp.remove(temp.size()-1);
            
            findPath(root.left,sum-root.val);
            
            findPath(root.right,sum-root.val);
            
    //返回前一个结点之前,移除当前节点的值
            temp.remove(temp.size()-1);

        }

    }
}

二叉搜索树的第k个节点

 /**
     * 给定一棵二叉搜索树,请找出其中的第k小的结点。
     * 例如, (5,3,7,2,4,6,8)    中,按结点数值大小顺序第三小结点的值为4。
     * 中序遍历一下,变成 小 中 大,然后找出第k小的数
     */
    TreeNode KthNode(TreeNode pRoot, int k)
    {
        if (k <= 0) {
            return null;
        }
        ArrayList<TreeNode> resultLists = new ArrayList<>();
        inOrder(pRoot, resultLists, k);
        if (k > resultLists.size()) {
            return null;
        }
        return resultLists.get(k - 1);
    }
    public void inOrder(TreeNode root, ArrayList<TreeNode> resultLists, int k) {
        if (resultLists.size() >= k) {
            return;
        }
        if (root != null) {
            inOrder(root.left, resultLists, k);
            resultLists.add(root);
            inOrder(root.right, resultLists, k);
        }
    }

判断两个二叉树是否相等

public  boolean isSameTree(TreeNode tree1,TreeNode tree2){
        if (tree1==null&&tree2==null){//若两棵树均为空
            return true;
        }
        else if (tree1==null||tree2==null){//若两棵树有一方为空
            return false;
        }
         if(tree1!=null&&tree2!=null){
            if(tree1.val!=tree2.val){
                return false;
            }
            else {
                return isSameTree(tree1.left,tree2.left)&&isSameTree(tree1.right,tree2.right);
            }
        }
     return false;   
    }

检查是否为二叉搜索树

public boolean checkBST(TreeNode root) {
        return check(root, Long.MIN_VALUE, Long.MAX_VALUE);
    }

    public boolean check(TreeNode root, long min, long max) {
        if (root == null) return true;
        if (root.val <= min || root.val >= max) return false;
        return check(root.left, min, root.val)
               && check(root.right, root.val, max);
  }

Attention:
注意参数min,max不可用Integer.MIN_VALUE,Integer.MAX_VALUE,因为节点的val是int类型,所以会存在样例通不过 if (root.val <= min || root.val >= max) return false;    的情况

寻找下一个节点

请设计一个算法,寻找二叉树中指定结点的下一个结点(即中序遍历的后继)。

给定树的根结点指针TreeNode* root和结点的值int p,请返回值为p的结点的后继结点的值。
保证结点的值大于等于零小于等于100000且没有重复值,若不存在后继返回-1import java.util.*;
 
/*
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;
    public TreeNode(int val) {
        this.val = val;
    }
}*/
public class Successor {
 public int findSucc(TreeNode root, int p) {
        boolean isFound = false;
        Stack<TreeNode> stack = new Stack<>();
        TreeNode curNode = root;
 
        while(curNode != null || !stack.isEmpty()){
            //将从根节点到最左边的左子树依次全部压入栈中
            while(curNode != null){
                stack.add(curNode);
                curNode = curNode.left;
            }
 
            //在从最左边的结点开始依次弹出,并且遍历它的所有的右子树
            if(!stack.isEmpty()){
                TreeNode q = stack.pop();
                if(isFound)
                    return q.val;
                else if(q.val == p)
                    isFound = true;
                curNode = q.right;
            }
        }
 
        return -1;
    }
}

判断完全二叉树

public boolean checking(TreeNode root) {
    Queue<TreeNode> queue = new LinkedList<TreeNode>();
    boolean leaf = false; // 叶子结点
    TreeNode left;
    TreeNode right;
    queue.add(root);
    while (!queue.isEmpty()) {
      root = queue.poll();
      left = root.left;
      right = root.right;
      if ((leaf&&(left!=null||right!=null)) || (left==null&&right!=null)) {
        // 如果之前层遍历的结点没有右孩子,且当前的结点有左或右孩子,直接返回false
        // 如果当前结点有右孩子却没有左孩子,直接返回false
        return false;
      }
      if (left != null) {
        queue.offer(root.left);
      }
      if (right != null) {
        queue.offer(root.right);
      }else {
        leaf = true; // 如果当前结点没有右孩子,那么之后层遍历到的结点必须为叶子结点
      }
    }
    return true;
  }

参考链接

二叉树基本操作及面试题(你想要的都有)
一篇文章搞定面试中的二叉树题目(java实现)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值