Java 数据结构进阶二叉树题集上

 更新时间:2022年04月01日 18:04:30   作者:Pretend..  
二叉树可以简单理解为对于一个节点来说,最多拥有一个上级节点,同时最多具备左右两个下级节点的数据结构。本文将带你通过实际题目来熟练掌握

二叉树操作的代码大多数使用递归来实现,代码会比较简洁,如果使用非递归,代码会比较的繁荣,而且不易理解。(上)中的题偏向于基础,后面(下)中的题机会比较难。

1、二叉树的遍历

(1)前、中、后序遍历

这里写到的遍历是递归遍历,代码比较简单,后续会写非递归的代码。以前序遍历为例:

如果根节点root为空,直接返回,否则,打印根节点,再分别递归root的左子树和右子树即可。中序遍历的话,先中序遍历左子树,打印根节点,再中序遍历右子树即可。

【代码如下】

//递归实现,比较简单
public void preTree(Node root){
        if(root==null){
            return;
        }
        System.out.print(root.val+" ");
        preTree(root.left);
        preTree(root.right);
    }

(2)层序遍历

【OJ链接】

OJ的返回值为一个存放链表的链表,所以我们可以将每一层的元素存放在同一个链表中,作为元素存放在要返回的链表中。还是使用队列来遍历链表,每次出根节点,当其左右节点不为空的时候,入左右节点。直到队列为空,遍历完成。

如何判断二叉树每层结点的个数?

在对每层节点出队完成后,队列中剩余结点的个数就是下一层结点的个数。比如:现在给队列如跟节点,队列大小为1,第一层的节点个数就为1;当根节点出对后,我们需要入队根节点的左右节点,如果左节点为null,则只入右节点,此时队列大小为1,第二层的节点个数就为1。

【代码如下】

public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> ret=new ArrayList<>();
        if(root==null){
            return ret;
        }
        Queue<TreeNode> queue=new LinkedList<>();
        queue.offer(root);
        while(!queue.isEmpty()){
            List<Integer> list=new ArrayList<>();
            int size=queue.size();
            while(size--!=0){
                TreeNode node=queue.poll();
                list.add(node.val);
                if(node.left!=null){
                    queue.offer(node.left);
                }
                if(node.right!=null){
                    queue.offer(node.right);
                }
            }
            ret.add(list);
        }
        return ret;
    }

2、获取树中子结点的个数

通常二叉树的问题,都会有两种思路:遍历思路和子问题思路。

如这道题:

我们可以求出它的左子树和右子树中子结点的个数,相加即可;或者,定义计数器,因为要递归,所以我们需要一个全局变量(count),递归左右子树,只要遇到子节点,count就加一。

【代码如下】

//获取叶子节点的个数
    //方法一
    public int getLeafNodeCount1(Node root){
        if(root==null){
            return 0;
        }
        if(root.left==null&&root.right==null){
            return 1;
        }
        return getLeafNodeCount1(root.left)+getLeafNodeCount1(root.right);
    }
    // 方法二
    public static int count1;
    public void getLeafNodeCount2(Node root){
        if(root==null){
            return ;
        }
        if(root.left==null&&root.right==null){
            count1++;
        }
        getLeafNodeCount2(root.left);
        getLeafNodeCount2(root.right);
    }

3、获取二叉树的高度

获取二叉树的高度,我们只需要获取二叉树左右子树的高度,返回左右子树的最大高度加一即可。

【代码如下】

 // 获取二叉树的高度
    public int getHeight(Node root){
        if(root==null){
            return 0;
        }
        int left=getHeight(root.left);
        int right=getHeight(root.right);
        return left>right?left+1:right+1;
    }

4、判断是不是完全二叉树

【完全二叉树和满二叉树】

  • 满二叉树: 一棵二叉树,如果每层的结点数都达到最大值,则这棵二叉树就是满二叉树。也就是说,如果一棵二叉树的层数为K,且结点总数是 2^K-1,则它就是满二叉树。
  • 完全二叉树: 完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从0至n-1的结点一一对应时称之为完全二叉树。 要注意的是满二叉树是一种特殊的完全二叉树。

判断完全二叉树,我们可以借助队列来实现,在二叉树不为空的情况下,对二叉树进行层序遍历:定义一个队列,将根节点放入,只要队列不为空,进行出队,将得到的节点的左右节点入队,注意先左后右,节点为空也要进行入队(队列可以存储null)。直到遇到第一个出队的节点为null,对队列中剩下的元素进行遍历,如果全为null,则为完全二叉树;如果存在不为null的结点,则不是完全二叉树。

 public boolean isCompleteTree(Node root){
       Queue<Node> queue=new LinkedList<>();
       queue.offer(root);
       //如果队列为空,会存在空指针异常
       while(!queue.isEmpty()){
           //层序遍历
           Node node=queue.poll();
           if(node!=null){
               //将节点的左右子节点放入队列
               queue.offer(node.left);
               queue.offer(node.right);
           }else{
               //如果node为null,直接对队列进行判断
               break;
           }
       }
       int x=queue.size();
       //判断队列元素是否全为null
       for(int i=0;i<x;++i){
           if(queue.poll()!=null){
               return false;
           }
       }
       return true;
    }

5、判断两个树是否相同

【OJ链接】

存在以下四种情况:

 【代码如下】

class Solution {
    public boolean isSameTree(TreeNode p, TreeNode q) {
        if(p==null&&q!=null||p!=null&&q==null){
            return false;
        }
        if(p==null&&q==null){
            return true;
        }
        if(p.val!=q.val){
            return false;
        }
        return isSameTree(p.left,q.left)&&isSameTree(p.right,q.right);
    }
}

6、另一棵树的子树

【OJ链接】

上面已经给写过判断两棵树是否相等的题,我们只需要判断树p是否等于树q,或者数p的左子树或右子树是否等于树q。分为以下几种情况:

 【代码如下】

class Solution {
    //判断两个树是否相等
    public boolean isSameTree(TreeNode root,TreeNode subRoot){
        if(root==null&&subRoot!=null||root!=null&&subRoot==null){
            return false;
        }
        if(root==null&&subRoot==null){
            return true;
        }
        if(root.val!=subRoot.val){
            return false;
        }
        return isSameTree(root.left,subRoot.left)&&isSameTree(root.right,subRoot.right);
    }
    //判断子树
    public boolean isSubtree(TreeNode root, TreeNode subRoot) {
        if(root==null||subRoot==null){
             return false;
        }
        if(isSameTree(root,subRoot)){
            return true;
        }
        return isSubtree(root.left,subRoot)||isSubtree(root.right,subRoot);
    }
}

7、判断平衡二叉树

【OJ链接】

高度平衡二叉树定义为:

一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。

首先我们需要写一个函数来求二叉树的高度,只要这个二叉树的左右子树高度差不大于1,且左右子树都是平衡二叉树,则其为平衡二叉树。

【代码如下】

class Solution {
    //求二叉树的高度
    public int maxDepth(TreeNode root){
        if(root==null){
            return 0;
        }
        int left=maxDepth(root.left);
        int right=maxDepth(root.right);
        return left>right?left+1:right+1;
    }
    //判断二叉树是不是平衡二叉树
    public boolean isBalanced(TreeNode root) {
        if(root==null){
            return true;
        }
        if(Math.abs(maxDepth(root.left)-maxDepth(root.right))<=1){
            return isBalanced(root.left)&&isBalanced(root.right);
        }
        return false;
    }
}

 

到此这篇关于Java 数据结构进阶二叉树题集上的文章就介绍到这了,更多相关Java 二叉树内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringMVC中使用@PathVariable绑定路由中的数组的方法

    SpringMVC中使用@PathVariable绑定路由中的数组的方法

    这篇文章主要介绍了SpringMVC中使用@PathVariable绑定路由中的数组的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-07-07
  • java实现屏蔽词功能

    java实现屏蔽词功能

    这篇文章主要介绍了java实现屏蔽词功能,类似贴吧里面屏蔽各种用户的发帖内容,感兴趣的小伙伴们可以参考一下
    2015-12-12
  • Java处理压缩文件的步骤详解

    Java处理压缩文件的步骤详解

    在Java编程环境中,处理zip压缩文件是一项常见的任务,特别是在数据传输、备份或者打包应用程序时,本文将详细讲解Java处理压缩文件的步骤,并有相关的代码示例供大家参考,需要的朋友可以参考下
    2024-10-10
  • Springboot指定扫描路径的实现示例

    Springboot指定扫描路径的实现示例

    本文主要介绍了Springboot指定扫描路径的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-05-05
  • mybatis整合ehcache做三级缓存的实现方法

    mybatis整合ehcache做三级缓存的实现方法

    ehcache是一个快速内存缓存框架,java项目里用起来很方便,下面这篇文章主要给大家介绍了关于mybatis整合ehcache做三级缓存的实现方法,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-06-06
  • Java详解Swing中的几种常用按钮的使用

    Java详解Swing中的几种常用按钮的使用

    这篇文章主要介绍了怎么用Java来创建和使用Swing中的几种常用按钮,按钮是我们经常要用的工具,但是你有想过自己怎么去实现它吗,感兴趣的朋友跟随文章往下看看吧
    2022-04-04
  • MyBatis中高级多表查询(ResultMap、association、collection)详解

    MyBatis中高级多表查询(ResultMap、association、collection)详解

    文章主要介绍了MyBatis中高级多表查询的四种方式:ResultMap、association、collection以及自连接查询,通过定义接口的抽象方法、编写mapper.xml和测试类,详细展示了如何根据复杂数据结构进行数据的装配和查询,感兴趣的朋友一起看看吧
    2024-11-11
  • IDEA2023版本创建Spring项目只能勾选17和21却无法使用Java8的完美解决方案

    IDEA2023版本创建Spring项目只能勾选17和21却无法使用Java8的完美解决方案

    想创建一个springboot的项目,本地安装的是1.8,但是在使用Spring Initializr创建项目时,发现版本只有17和21,这篇文章主要介绍了IDEA2023版本创建Sping项目只能勾选17和21,却无法使用Java8的解决方法,需要的朋友可以参考下
    2023-12-12
  • SpringBoot集成iTextPDF的实例

    SpringBoot集成iTextPDF的实例

    SpringBoot集成iTextPDF时,创建PDF文档涉及Document、PdfPTable和PdfPCell对象,设置文档大小和页边距,使用Paragraph设置段落样式,并通过Table和Cell控制表格样式和对齐,还可加入图片美化文档,这些步骤对于生成具有中文内容的PDF文件至关重要
    2024-09-09
  • SpringBoot整合SpringSecurity实现认证拦截的教程

    SpringBoot整合SpringSecurity实现认证拦截的教程

    我们写的任何一个项目,都应该有安全防护,不应该让这个项目进行“裸奔”,否则很容易被别人进行攻击。而在SpringBoot环境中,其实可以很容易实现安全保护,本文给大家介绍SpringBoot如何整合SpringSecurity实现认证拦截,需要的朋友可以参考下
    2023-05-05

最新评论