数据结构之你真的了解二叉树吗

简述

你真的了解二叉树吗?
一棵二叉树是结点的一个有限集合,该集合或者为空,或者是由一个根节点加上两棵别称为左子树和右子树的二叉树组成。
这是表面上的二叉树,本文将基于二叉树的前中后序遍历解决一些求解二叉树的相关问题,感兴趣的就继续往下看吧。

定义二叉树的结点

二叉树是结点的有限集合,那么结点就必不可少啦:

public class TreeNode {
    public TreeNode left;
    public TreeNode right;
    public int value;

    public TreeNode(int value) {
        this.value = value;
    }
}

二叉树的前中后序遍历

二叉树的前中后序遍历运用了递归的方法,根结点单独考虑,然后对左右子树采用相同的方法:

public class TreeTraversal {
    //前序遍历
    public static void preTraversal(Node root){
        if(root!=null) {
            System.out.printf("%c",root.val);
            preTraversal(root.left);
            preTraversal(root.right);
        }else{
            //不处理
        }
    }

    //中序遍历
    public static void inTraversal(Node root){
        if(root!=null){
            inTraversal(root.left);
            System.out.printf("%c",root.val);
            inTraversal(root.right);
        }else{}
    }

    //后序遍历
    public static void postTraversal(Node root){
        if(root!=null){
            postTraversal(root.left);
            postTraversal(root.right);
            System.out.printf("%c",root.val);
        }else{}
    }
}

你品,你细品,这方法是不是很巧妙,那么接下来,别眨眼,套路他这就来了…

计算结点个数

计算二叉树结点的个数

public static int sumNodeSize(Node root){
        if(root==null){
            return 0;
        }else {
            int rootNodeSize = 1;//根结点单独考虑
            //对左右子树采用相同的方法
            int leftNodeSize = sumNodeSize(root.left);
            int rightNOdeSize = sumNodeSize(root.right);
            return rootNodeSize + leftNodeSize + rightNOdeSize;
        }
    }

第k层结点个数

求二叉树第k层结点个数

public static int sumKlevelNodeSize(TreeNode root,int k){
        //根结点单独考虑
        if(root==null){
            return 0;
        }else if(k==1){
            return 1;
        }else{
            //对左右子树采用相同的方法
            int leftsumk_1=sumKlevelNodeSize(root.left,k-1);
            int rightsumk_1=sumKlevelNodeSize(root.right,k-1);
            return leftsumk_1+rightsumk_1;
        }
    }

二叉树的高度

给定一棵二叉树,求它的高度:

public static int getHeight(TreeNode root){
        //根结点单独考虑
        if(root==null){
            return 0;
        }else if(root.left==null&&root.right==null){
            return 1;
        }else{
            //对左右子树采用相同的方法
            int leftheight=getHeight(root.left);
            int rightheight=getHeight(root.right);
            return Math.max(leftheight,rightheight)+1;
        }
    }

是否有结点值为v

给定一棵二叉树,给定一个值,判断二叉树中是否包含值为指定值的结点:

public static boolean contains(TreeNode root,int v){
        //根结点单独考虑
        if(root==null){
            return false;
        }else if(root.value==v){
            return true;
        }else{
            //对左右子树采用相同的方法
            boolean leftCon=contains(root.left,v);

            if(leftCon){
                return true;
            }else {
                boolean rightCon=contains(root.right,v);
                if(rightCon){
                    return true;
                }else{
                    return false;
                }
            }
        }
    }

怎么样是不是很惊喜,我连注释的文案都没改呢。
下面再奉上一些相关面试题,里面也有相关应用,入股不亏!

平衡二叉树

输入一棵二叉树的根节点,判断该树是不是平衡二叉树。如果某二叉树中任意节点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树。
此处提供一种思路:求结点左右子树高度再通过高度差判断是否为平衡二叉树。

public class balanceTreeJZ55 {
    public boolean isBalanced(TreeNode root) {
        //单独考虑根结点
        if(root==null){
            return true;
        }
        //用到刚才求高度的方法
        int lefth=getHeight(root.left);
        int righth=getHeight(root.right);
        int dif=lefth-righth;
        //判断高度差是否<=1
        if(!(dif==-1||dif==0||dif==1)){
            return false;
        }
        //对左右子树采用相同的方法 得到的结果结合得出最终结果
        return isBalanced(root.left)&&isBalanced(root.right);
    }

    private int getHeight(TreeNode root) {
        if(root==null){
            return 0;
        }
        return Math.max(getHeight(root.right),getHeight(root.left))+1;
    }
}

另一个树的子树

给定两个非空二叉树 s 和 t,检验 s 中是否包含和 t 具有相同结构和节点值的子树。s 的一个子树包括 s 的一个节点和这个节点的所有子孙。s 也可以看做它自身的一棵子树。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/subtree-of-another-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

此处提供一种思路:如果s为空树,那么一定返回false,如果s跟q的值相等,那么需要单独判断他们两是否为相同的树,相同的话,就返回true,不相同继续判断,最后,继续判断左子树右子树是否包含就可以了。

public class isSonTree572 {
    //判断是否为相同树
    public boolean isSameTree(TreeNode p, TreeNode q) {
        //两者皆为空树
        if(p==null&&q==null){
            return true;
        }
        //有一个是空树
        if(p==null||q==null){
            return false;
        }
        //根结点相等并且左右子树也互为相同树 
        return p.value==q.value&&isSameTree(p.left,q.left)&&isSameTree(p.right,q.right);
    }

    public boolean isSubtree(TreeNode s, TreeNode t) {
        //s为空时
        if(s==null){
            return false;
        }
        //根结点就相等时
        if(s.value==t.value){
            if(isSameTree(s,t)){
                return true;
            }
        }
        //通过对左右子树采用相同的方法  判断左右子树是否有该子树
        if(isSubtree(s.left,t)){
            return true;
        }
        return isSubtree(s.right,t);
    }
}

二叉树的最近公共祖先

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

此处提供一种方法,当两个结点都在左子树中那么最近公共祖先也在里面(右同),如果一个在左子树,一个在右子树那么最近公共祖先就是根结点。需要单独写一个方法判断结点是在左子树还是右子树,详见代码:

public class nearestAncestor236 {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        //根结点单独考虑
        if(p==root||q==root){
            return root;
        }
        //对左右子树采用相同的方法
        boolean pInleft=search(root.left,p);
        boolean qInleft=search(root.left,q);

        //两个结点都在左子树
        if(pInleft&&qInleft){
            return lowestCommonAncestor(root.left,p,q);
        }
        //两个结点都在右子树
        else if(!pInleft&&!qInleft){
            return lowestCommonAncestor(root.right,p,q);
        }

        //一个在左 一个在右 最近祖先为根结点
        else{
            return root;
        }
    }

    //单独写一个方法判断结点在左子树还是右子树 即判断以root为跟的子树里是否有t结点
   private boolean search(TreeNode root, TreeNode t) {
        //根为空
        if(root==null){
            return false;
        }
        //跟结点就是
        if(root==t){
            return true;
        }
        //对左右子树采用相同的方法
        return search(root.left,t)||search(root.right,t);
    }
}

好啦,看了这么多题目是不是有晕,反正小编是有点脑壳疼了,慢慢消化吧,我们下期再见,如有误之处还请批评指正。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值