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

目录
  • 1、对称二叉树
  • 2、创建并遍历二叉树
  • 3、二叉树中两节点最近公共祖先
  • 4、二叉搜索树与双向链表
  • 5、根据前序和中序遍历结果创建二叉树
  • 6、二叉树创建字符串
  • 7、非递归实现二叉树前序遍历
  • 8、非递归实现二叉树后序遍历

1、对称二叉树

【OJ链接】

分为以下几种情况:

  • 二叉树为空,是对称二叉树
  • 二叉树不为空,其左子树或者右子树为空,不是对称二叉树
  • 二叉树不为空,左右子树都为空,是对称二叉树
  • 二叉树不为空,左右子树不为空,左右子节点值不同,不是对称二叉树
  • 二叉树不为空,左右子树不为空,左右子节点值相同,如果左子树的左节点和右子树的右节点、左子树的右节点和右子树的左节点相同,则其为对称二叉树,否则,不是对称二叉树。

【代码如下】

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

2、创建并遍历二叉树

【OJ链接】

【题目描述】

读入用户输入的一串先序遍历字符串,根据此字符串建立一个二叉树(以指针方式存储)。 例如如下的先序遍历字符串: ABC##DE#G##F### 其中“#”表示的是空格,空格字符代表空树。建立起此二叉树以后,再对二叉树进行中序遍历,输出遍历结果。

关于这个题,完全从零开始,我们需要定义(1)二叉树的节点,(2)中序遍历的函数,(3)根据先序遍历字符串创建二叉树的函数,(4)主函数。创建节点、中序遍历、主函数不用多说。主要说一下根据先序遍历字符串来创建二叉树的过程:

遍历字符串,#表示空,就分为以下两种情况:如果字符不为空,我们需要创建根节点,然后递归创建其的左右子树;否则,直接跳过即可。

【代码如下】

import java.util.Scanner;
    //定义二叉树的节点
    class TreeNode{
        public char val;
        public TreeNode left;
        public TreeNode right;
        public  TreeNode(char val){
            this.val=val;
        }
    }
public class Main {
    //根据先序遍历字符串创建二叉树
    public static int i=0;
    public static TreeNode createTree(String s){
        TreeNode root=null;
        //字符不为空的情况下,创建根节点
        if(s.charAt(i)!='#'){
            root=new TreeNode(s.charAt(i));
            i++;
            //递归创建root的左右子树
            root.left=createTree(s);
            root.right=createTree(s);
        }else{
            //字符为空,直接跳过
            i++;
        }
        return root;
    }
    public static void inorderTree(TreeNode root){
        if(root==null){
            return;
        }
        inorderTree(root.left);
        System.out.print(root.val+" ");
        inorderTree(root.right);
    }
    //中序遍历二叉树
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while (in.hasNextLine()){
            String s=in.nextLine();
            TreeNode node=createTree(s);
            inorderTree(node);
        }
    }
}

3、二叉树中两节点最近公共祖先

【OJ链接】

二叉树的根节点为root,以及两个节点p、q,如果二叉树为空,则返回null;如果二叉树的根节点等于p或者q,或者p、q在根节点的左右两侧,则其最近公共结点为root;如果p、q系欸但在root节点的同侧,则最小公共结点就是该侧的节点。

【代码如下】

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root==null){
            return null;
        }
        if(root==q||root==p){
            return root;
        }
        TreeNode left=lowestCommonAncestor(root.left,p,q);
        TreeNode right=lowestCommonAncestor(root.right,p,q);
        if(left==null){
            return right;
        }
        if(right==null){
            return left;
        }
        return root;
    }
}

4、二叉搜索树与双向链表

【OJ链接】

二叉搜索树:任何节点的左子树小于右子树

将二叉搜索树转换为有序的双向链表:

二叉搜索树的中序遍历结果为有序的。所以我们只需要写一个中序遍历,在其中实现其节点左右指向的改变即可。首先我们需要一个前驱节点prev来保存每个节点的左节点,初始为null,因为是双向链表,所以prev还需要指向它的右节点,如果其为空,则不用。

【代码如下】

public class Solution {
    public TreeNode prev=null;
    //中序遍历二叉树
    public void inorderTree(TreeNode root){
        if(root==null){
            return ;
        }
        inorderTree(root.left);
        //处理二叉树的左右节点
        root.left=prev;
        if(prev!=null){
            prev.right=root;
        }
        prev=root;
        inorderTree(root.right);
    }
    public TreeNode Convert(TreeNode pRootOfTree) {
        if(pRootOfTree==null){
            return null;
        }
        inorderTree(pRootOfTree);
        while(pRootOfTree.left!=null){
            pRootOfTree=pRootOfTree.left;
        }
        return pRootOfTree;
    }
}

5、根据前序和中序遍历结果创建二叉树

【OJ链接】

给出一个二叉树的前序遍历和中序遍历的结果,根据其创建二叉树:

我们知道,前序遍历的第一个元素(prev)一定是根节点(从前往后遍历),所以在中序遍历中找到prev,则左边元素为左子树元素,右边元素为右子树,创建根节点,递归创建左子树和右子树。注意一定要先创建左子树,因为先序遍历的因素,先序遍历数组的下一个元素一定是左子树的根节点。【如果是根据后序遍历和中序遍历创建二叉树,则后序遍历的数组需要从后往前遍历,还有,一定要先递归创建右子树】

【代码如下】

class Solution {
    public int prevIndex=0;
    //找到preorder的prevIndex下标元素在inorder中的位置
    public int findIndex(int[] preorder,int[] inorder,int inbegin,int inend){
        for(int i=inbegin;i<=inend;++i){
            if(inorder[i]==preorder[prevIndex]){
                return i;
            }
        }
         return -1;
    }
    //创建二叉树
    public TreeNode buildTreeChild(int[] preorder,int[] inorder,int inbegin,int inend){
        if(inbegin>inend){
            return null;
        }
        TreeNode root=new TreeNode(preorder[prevIndex]);
        int index=findIndex(preorder,inorder,inbegin,inend);
        prevIndex++;
        root.left=buildTreeChild(preorder,inorder,inbegin,index-1);
        root.right=buildTreeChild(preorder,inorder,index+1,inend);
        return root;
    }
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        return buildTreeChild(preorder,inorder,0,inorder.length-1);
    }
}

6、二叉树创建字符串

【OJ链接】

字符串拼接,可以创建StringBuilder方便拼接,先将根节点拼接入字符串,如果其左子树不为空,拼接左括号,递归左子树,递归完后拼接右括号;左树为空的情况下,如果右树也为空,直接拼接右括号,否则,我们拼接空括号,递归右子树,之后再拼接右括号。

【代码如下】

class Solution {
    public void tree2strChild(TreeNode root,StringBuilder str){
        if(root==null){
            return;
        }
        str.append(root.val);
        if(root.left!=null){
            str.append("(");
            tree2strChild(root.left,str);
            str.append(")");
        }else{
            if(root.right==null){
                return;
            }else{
                str.append("()");
            }
        }
        if(root.right==null){
            return;
        }else{
            str.append("(");
            tree2strChild(root.right,str);
            str.append(")");
        }
    }
    public String tree2str(TreeNode root) {
        StringBuilder str=new StringBuilder();
        tree2strChild(root,str);
        return str.toString();
    }
}

7、非递归实现二叉树前序遍历

【OJ链接】

可以用栈来实现。定义一个栈,将根节点入栈后,去入栈左节点、左节点的左节点……直到为空,去除栈顶元素,入栈其右节点,知道为空,以此循环即可。(中序遍历和前序遍历思路相同)

【代码如下】

class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> list=new ArrayList<>();
        Stack<TreeNode> stack=new Stack<>();
        TreeNode cur=root;
        while(cur!=null||!stack.empty()){
            while(cur!=null){
                stack.push(cur);
                list.add(cur.val);
                cur=cur.left;
            }
            TreeNode node=stack.pop();
            cur=node.right;
        }
        return list;
    }
}

8、非递归实现二叉树后序遍历

【OJ链接】

初始化一个空栈。当【根节点不为空】或者【栈不为空】时,从根节点开。每次将当前节点压入栈中,如果当前节点有左子树,就往左子树跑,没有左子树就往右子树跑。若当前节点无左子树也无右子树,从栈中弹出该节点,如果当前节点是上一个节点(即弹出该节点后的栈顶元素)的左节点,尝试访问上个节点的右子树,如果不是,那当前栈的栈顶元素继续弹出。

【代码如下】

class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> list=new ArrayList<>();
        Stack<TreeNode> stack=new Stack<>();
        TreeNode cur=root;
        TreeNode prev=null;
        while(cur!=null||!stack.empty()){
            while(cur!=null){
                stack.push(cur);
                cur=cur.left;
             }
            TreeNode top=stack.peek();
            if(top.right==null||top.right==prev){
                list.add(top.val);
                stack.pop();
                prev=top;
            }else{
                cur=top.right;
            }
        }
      return list;
    }
}

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

(0)

相关推荐

  • 带你了解Java数据结构和算法之二叉树

    目录 1.树 2.二叉树 3.查找节点 4.插入节点 5.遍历树 6.查找最大值和最小值 7.删除节点 ①.删除没有子节点的节点 ②.删除有一个子节点的节点 ③.删除有两个子节点的节点 ④.删除有必要吗? 8.二叉树的效率 9.用数组表示树 10.完整的BinaryTree代码 11.哈夫曼(Huffman)编码 ①.哈夫曼编码 ②.哈夫曼解码 12.总结 1.树 树(tree)是一种抽象数据类型(ADT),用来模拟具有树状结构性质的数据集合.它是由n(n>0)个有限节点通过连接它们的边组成一个

  • Java数据结构之平衡二叉树的实现详解

    目录 定义 结点结构 查找算法 插入算法 LL 型 RR 型 LR 型 RL 型 插入方法 删除算法 概述 实例分析 代码 完整代码 定义 动机:二叉查找树的操作实践复杂度由树高度决定,所以希望控制树高,左右子树尽可能平衡. 平衡二叉树(AVL树):称一棵二叉查找树为高度平衡树,当且仅当或由单一外结点组成,或由两个子树形 Ta 和 Tb 组成,并且满足: |h(Ta) - h(Tb)| <= 1,其中 h(T) 表示树 T 的高度 Ta 和 Tb 都是高度平衡树 即:每个结点的左子树和右子树的高

  • Java数据结构最清晰图解二叉树前 中 后序遍历

    目录 一,前言 二,树 ①概念 ②树的基础概念 三,二叉树 ①概念 ②两种特殊的二叉树 ③二叉树的性质 四,二叉树遍历 ①二叉树的遍历 ②前序遍历 ③中序遍历 ④后序遍历 五,完整代码 一,前言 二叉树是数据结构中重要的一部分,它的前中后序遍历始终贯穿我们学习二叉树的过程,所以掌握二叉树三种遍历是十分重要的.本篇主要是图解+代码Debug分析,概念的部分讲非常少,重中之重是图解和代码Debug分析,我可以保证你看完此篇博客对于二叉树的前中后序遍历有一个新的认识!!废话不多说,让我们学起来吧!!

  • 详解Java数据结构之平衡二叉树

    目录 什么是二叉搜索树 平衡二叉搜索树 平衡二叉搜索树建树程序 计算每个节点的高度 计算每个节点的平衡因子 合并二叉树 旋转调整函数 整体代码 什么是二叉搜索树 简单来说,就是方便搜索的二叉树,是一种具备特定结构的二叉树,即,对于节点n,其左子树的所有节点的值都小于等于其值,其右子树的所有节点的值都大于等于其值.​ 以序列2,4,1,3,5,10,9,8为例,如果以二叉搜索树建树的方式,我们建立出来的逐个步骤应该为 第一步: 第二步: 第三步: 第四步: 第五步: 第六步: 第七步: 第八步:

  • Java数据结构之平衡二叉树的原理与实现

    目录 1 平衡二叉树的概述 2 平衡二叉树的实现原理 2.1 单旋转 2.2 双旋转 2.3 总结 3 平衡二叉树的构建 3.1 类架构 3.2 查找的方法 3.3 检查是否平衡的方法 3.4 插入的方法 3.5 查找最大值和最小值 3.6 删除的方法 4 平衡二叉树的总结 平衡二叉树(AVL树),顾名思义,是一颗很“平衡”的树,它的平衡是相对于排序二叉树来说的.为了避免极端情况下二叉搜索树节点分布不均匀,甚至退化为链表,影响查找效率,我们引入了平衡二叉树,即让树的结构看起来尽量“均匀”,左右子

  • Java数据结构二叉树难点解析

    前言 本章,我们主要需要了解以下内容 什么是线索二叉树 怎么去把二叉树线索化 怎么通过线索二叉树查找某个数的后继结点 二叉树的查看--二叉树怎们遍历 什么是线索二叉树 首先我们来了解一下什么是线索二叉树? 定义:一个二叉树通过如下的方法"穿起来":所有原本为空的右(孩子)指针改为指向该节点在中序序列中的后继,所有原本为空的左(孩子)指针改为指向该节点的中序序列的前驱. 再看一下为什么要有线索二叉树? 顾名思义,线索二叉树,肯定是根据线索查找,查找速度肯定更快. 线索二叉树能线性地遍历二

  • java数据结构之搜索二叉树

    本文实例为大家分享了java数据结构之搜索二叉树的具体代码,供大家参考,具体内容如下 搜索二叉树的定义是:在一个二叉树上,左节点一定比父节点小,右节点一定比父节点大,其他定义跟二叉树相同. 代码实现: public class node {     int data;     public node left, right=null;       public node(int data) {         this.data = data;       }       public node

  • Java 数据结构中二叉树前中后序遍历非递归的具体实现详解

    目录 一.前序遍历 1.题目描述 2.输入输出示例 3.解题思路 4.代码实现 二.中序遍历 1.题目描述 2.输入输出示例 3.解题思路 4.代码实现 三.后序遍历 1.题目描述 2.输入输出示例 3.解题思路 4.代码实现 一.前序遍历 1.题目描述 给你二叉树的根节点 root ,返回它节点值的 前序 遍历. 2.输入输出示例 示例 1: 输入:root = [1,null,2,3] 输出:[1,2,3] 示例2: 输入:root = [] 输出:[] 示例 3: 输入:root = [1

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

    目录 1.对称二叉树 2.创建并遍历二叉树 3.二叉树中两节点最近公共祖先 4.二叉搜索树与双向链表 5.根据前序和中序遍历结果创建二叉树 6.二叉树创建字符串 7.非递归实现二叉树前序遍历 8.非递归实现二叉树后序遍历 1.对称二叉树 [OJ链接] 分为以下几种情况: 二叉树为空,是对称二叉树 二叉树不为空,其左子树或者右子树为空,不是对称二叉树 二叉树不为空,左右子树都为空,是对称二叉树 二叉树不为空,左右子树不为空,左右子节点值不同,不是对称二叉树 二叉树不为空,左右子树不为空,左右子节点

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

    目录 1.二叉树的遍历 (1)前.中.后序遍历 (2)层序遍历 2.获取树中子结点的个数 3.获取二叉树的高度 4.判断是不是完全二叉树 5.判断两个树是否相同 6.另一棵树的子树 7.判断平衡二叉树 二叉树操作的代码大多数使用递归来实现,代码会比较简洁,如果使用非递归,代码会比较的繁荣,而且不易理解.(上)中的题偏向于基础,后面(下)中的题机会比较难. 1.二叉树的遍历 (1)前.中.后序遍历 这里写到的遍历是递归遍历,代码比较简单,后续会写非递归的代码.以前序遍历为例: 如果根节点root为

  • Java数据结构之并查集的实现

    目录 代码解析 代码应用 实际应用 并查集就是将原本不在一个集合里面的内容合并到一个集合中. 在实际的场景中用处不多. 除了出现在你需要同时去几个集合里面查询,避免出现查询很多次,从而放在一起查询的情况. 下面简单实现一个例子,我们来举例说明一下什么是并查集,以及究竟并查集解决了什么问题. 代码解析 package com.chaojilaji.book.andcheck; public class AndCheckSet { public static Integer getFather(in

  • Java数据结构之常见排序算法(上)

    目录 认识排序 常见排序的分类 直接插入排序 希尔排序(缩小增量排序) 选择排序 堆排序 认识排序 在学校中,如果我们要参加运动会,或者军训的时候,会按照身高从矮到高进行站队,比如上课老师手上拿的考勤表,通常是按照学号从低到高进行排序的.再比如编程语言排行榜,也是在排序. 生活中有相当多的排序场景,由此可知,排序还是很重要的, 本章就会介绍常见的一些排序算法. 所谓排序呢,就拿我们上面的举例来说,会按照某个或某些关键字的大小,递增或者递减排列起来的操作,这就是排序,这里面也涉及到排序的稳定性,举

  • 详解Java实现数据结构之并查集

    ​一.什么是并查集 对于一种数据结构,肯定是有自己的应用场景和特性,那么并查集是处理什么问题的呢? 并查集是一种树型的数据结构,用于处理一些不相交集合(disjoint sets)的合并及查询问题,常常在使用中以森林来表示.在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中.其特点是看似并不复杂,但数据量极大,若用正常的数据结构来描述的话,往往在空间上过大,计算机无法承受:即使在空

  • Java数据结构学习之二叉树

    1 背景知识:树(Tree) 在之前的笔记中,我们介绍的链表.栈.队列.数组和字符串都是以线性结构来组织数据的.本篇笔记要介绍的树采用的是树状结构,这是一种非线性的数据组织形式. 树结构由节点和边构成,且不存在环.我们曾在线性表型的数据结构中介绍过循环链表和循环队列,这两种数据结构使得存储容器中的元素形成一个闭环,具体可参看"数据结构学习笔记"系列的相关博文,链接贴在下面: 链表:https://www.jb51.net/article/215278.htm 队列:https://ww

  • Java数据结构顺序表从零基础到精通进阶

    目录 一.什么是线性表 二.顺序表 三.手撕顺序表 属性定义 构造方法 接口实现 确保顺序表空间 增加元素 打印顺序表 判断顺序表中是否包含某个元素 查找元素 获取 pos 位置的元素 将 pos 位置的元素值设为 value 删除第一次出现的关键字key 获取顺序表长度 清空顺序表 删除所有的key 一.什么是线性表 线性表是最基本.最简单.也是最常用的一种数据结构.线性表*(linear list)*是数据结构的一种,一个线性表是n个具有相同特性的数据元素的有限序列.常见的线性表有顺序表,链

随机推荐