Java二叉树

目录

一、树形结构

1.1 概念

1.2 树的性质

1.3 树的表示形式

二、二叉树

2.1 概念

2.2 两种特殊的二叉树 

2.3 二叉树的性质 

2.4 二叉树的存储

2.5 二叉树的基本操作

2.5.1 二叉树的遍历

2.5.2 二叉树的基本操作 


一、树形结构

1.1 概念

树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。它具有以下的特点:

  • 有一个特殊的结点,称为根结点,根结点没有前驱结点
  • 除根结点外,其余结点被分成M(M > 0)个互不相交的集合T1、T2、......、Tm,其中每一个集合Ti (1 <= i <=m) 又是一棵与树类似的子树。每棵子树的根结点有且只有一个前驱,可以有0个或多个后继
  • 树是递归定义的

1.2 树的性质

结点的度:一个结点含有子树的个数称为该结点的度; 如上图:A的度为6
树的度:一棵树中,所有结点度的最大值称为树的度; 如上图:树的度为6
叶子结点或终端结点:度为0的结点称为叶结点; 如上图:B、C、H、I...等节点为叶结点
双亲结点或父结点:若一个结点含有子结点,则这个结点称为其子结点的父结点; 如上图:A是B的父结点
孩子结点或子结点:一个结点含有的子树的根结点称为该结点的子结点; 如上图:B是A的孩子结点
根结点:一棵树中,没有双亲结点的结点;如上图:A
结点的层次:从根开始定义起,根为第1层,根的子结点为第2层,以此类推

树的高度或深度:树中结点的最大层次; 如上图:树的高度为4

1.3 树的表示形式

树结构相对线性表就比较复杂了,要存储表示起来就比较麻烦了,实际中树有很多种表示方式,如:双亲表示法孩子表示法孩子双亲表示法孩子兄弟表示法等等。我们这里就简单的了解其中最常用的孩子兄弟表示法。

class Node {
    int value; // 树中存储的数据
    Node firstChild; // 第一个孩子引用
    Node nextBrother; // 下一个兄弟引用
}

二、二叉树

2.1 概念

一棵二叉树是结点的一个有限集合,该集合:
        1. 或者为空
        2. 或者是由一个根节点加上两棵别称为左子树右子树的二叉树组成。

 从上图可以看出:
        1. 二叉树不存在度大于2的结点
        2. 二叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序树

注意:对于任意的二叉树都是由以下几种情况复合而成的:

2.2 两种特殊的二叉树 

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

2.3 二叉树的性质 

1. 若规定根结点的层数为1,则一棵非空二叉树的第i层上最多有 2^{i-1}(i>0)个结点
2. 若规定只有根结点的二叉树的深度为1,则深度为K的二叉树的最大结点数是 2^k -1(k>=0)
3. 对任何一棵二叉树, 如果其叶结点个数为 n0, 度为2的非叶结点个数为 n2,则有n0=n2+1
4. 具有n个结点的完全二叉树的深度k为 log_{2}{(n+1)}上取整
5. 对于具有n个结点的完全二叉树,如果按照从上至下从左至右的顺序对所有节点从0开始编号,则对于序号为i的结点有

  • 若i>0,双亲序号:(i-1)/2;i=0,i为根结点编号,无双亲结点
  • 若2i+1<n,左孩子序号:2i+1,否则无左孩子
  • 若2i+2<n,右孩子序号:2i+2,否则无右孩子

2.4 二叉树的存储

二叉树的存储结构分为:顺序存储类似于链表的链式存储。
二叉树的链式存储是通过一个一个的节点引用起来的常见的表示方式有二叉和三叉表示方式,具体如下:

// 孩子表示法
class Node {
    int val; // 数据域
    Node left; // 左孩子的引用,常常代表左孩子为根的整棵左子树
    Node right; // 右孩子的引用,常常代表右孩子为根的整棵右子树
} 
// 孩子双亲表示法
class Node {
    int val; // 数据域
    Node left; // 左孩子的引用,常常代表左孩子为根的整棵左子树
    Node right; // 右孩子的引用,常常代表右孩子为根的整棵右子树
    Node parent; // 当前节点的根节点
}

2.5 二叉树的基本操作

2.5.1 二叉树的遍历

1. 前中后序遍历
学习二叉树结构,最简单的方式就是遍历。所谓遍历(Traversal)是指沿着某条搜索路线,依次对树中每个结点均做一次且仅做一次访问。访问结点所做的操作依赖于具体的应用问题(比如:打印节点内容、节点内容加1)。 遍历是二叉树上最重要的操作之一,是二叉树上进行其它运算之基础。

在遍历二叉树时,如果没有进行某种约定,每个人都按照自己的方式遍历,得出的结果就比较混乱,如果按照某种规则进行约定,则每个人对于同一棵树的遍历结果肯定是相同的。如果N代表根节点,L代表根节点的左子树,R代表根节点的右子树,则根据遍历根节点的先后次序有以下遍历方式:

  • NLR:前序遍历(Preorder Traversal 亦称先序遍历)——访问根结点--->根的左子树--->根的右子树。
  • LNR:中序遍历(Inorder Traversal)——根的左子树--->根节点--->根的右子树。
  • LRN:后序遍历(Postorder Traversal)——根的左子树--->根的右子树--->根节点。

下面主要分析前序递归遍历,中序与后序图解类似

前序遍历结果:1 2 3 4 5 6
中序遍历结果:3 2 1 5 4 6
后序遍历结果:3 2 5 6 4 1

2. 层序遍历
层序遍历:除了先序遍历、中序遍历、后序遍历外,还可以对二叉树进行层序遍历。设二叉树的根节点所在层数为1,层序遍历就是从所在二叉树的根节点出发,首先访问第一层的树根节点,然后从左到右访问第2层上的节点,接着是第三层的节点,以此类推,自上而下,自左至右逐层访问树的结点的过程就是层序遍历。
 

2.5.2 二叉树的基本操作 

1.对应的方法

public class MyTree {
    static class TreeNode{
        public int val;
        public TreeNode left;
        public TreeNode right;
        public TreeNode(int val) {
            this.val = val;
        }
    }
    // 获取树中节点的个数
    int size(TreeNode root) {
        return 0;
    }
    // 获取叶子节点的个数
    int getLeafNodeCount(TreeNode root){
        return 0;
    }
    // 子问题思路-求叶子结点个数
    // 获取第K层节点的个数
    int getKLevelNodeCount(TreeNode root,int k){
        return 0;
    }
    // 获取二叉树的高度
    int getHeight(TreeNode root){
        return 0;
    }
    // 检测值为value的元素是否存在
    TreeNode find(TreeNode root, int val){
        return null;
    }
    //层序遍历
    void levelOrder(TreeNode root){
        
    }
    // 判断一棵树是不是完全二叉树
    boolean isCompleteTree(TreeNode root){
        return false;
    }
}

2.二叉树的递归遍历 

    // 前序遍历
    public void preOrder(TreeNode root) {
        if(root == null) return;
        System.out.print(root.val+" ");
        preOrder(root.left);
        preOrder(root.right);
    }

    // 后序遍历
    public void laterOrder(TreeNode root) {
        if(root == null) return;
        preOrder(root.left);
        preOrder(root.right);
        System.out.print(root.val+" ");
    }

    //中序遍历
    public void inOrder(TreeNode root) {
        if(root == null) return;
        preOrder(root.left);
        System.out.print(root.val+" ");
        preOrder(root.right);
    }

3.获取二叉树节点个数 

    private static int nodeCount;
    // 获取树中节点的个数
    int size(TreeNode root) {
        if (root == null) {
            return 0;
        }
        nodeCount++;
        size(root.left);//对所有左数递归
        size(root.right);//对所有右数递归
        return nodeCount;
    }

    /**
     * 子问题求解节点个数
     * @param root
     * @return
     */
    int size2(TreeNode root){
        if (root == null) {
            return 0;
        }
        return size(root.left) + size(root.right) + 1;
    }

 4.获取二叉树叶子节点的个数

    // 获取叶子节点的个数
    private static int leafSize = 0;
    int getLeafNodeCount(TreeNode root){
        if (root == null) {
            return 0;
        }
        if (root.left == null && root.right == null) {
            leafSize++;
        }
        getLeafNodeCount(root.left);
        getLeafNodeCount(root.right);
        return leafSize;
    }

    // 子问题思路-求叶子结点个数
    int getLeafNodeCount2(TreeNode root){
        if (root == null) {
            return 0;
        }
        if (root.left == null && root.right == null) {
            return 1;
        }
        return getLeafNodeCount2(root.left) + getLeafNodeCount2(root.right);
    }

5.获取第k层节点的个数

    // 获取第K层节点的个数
    int getKLevelNodeCount(TreeNode root,int k){
        if (root == null) {
            return 0;
        }
        if (k == 1) {
            return 1;
        }
        return getKLevelNodeCount(root.left,k-1) + getKLevelNodeCount(root.right, k-1);
    }

 6.获取二叉树的高度

    int getHeight(TreeNode root){
        if (root == null) {
            return 0;
        }
        int leftH = getHeight(root.left);
        int rightH = getHeight(root.right);
        //求高度就是求左右两边最大的高度值
        return (leftH > rightH ? leftH : rightH) + 1;
    }

7.层序遍历

利用队列求解该问题

    void levelOrder(TreeNode root){
        Queue<TreeNode> queue = new LinkedList();
        if (root != null) {
            queue.offer(root);
        }
        while (!queue.isEmpty()) {
            TreeNode top = queue.poll();
            System.out.println(top.val);
            if (top.left != null) {
                queue.offer(top.left);
            }
            if (top.right != null) {
                queue.offer(top.right);
            }
        }
    }

8.判断一棵树是不是完全二叉树

    boolean isCompleteTree(TreeNode root){
        //这里利用队列求解这个问题
        Queue<TreeNode> queue = new LinkedList();
        if (root != null) {
            queue.offer(root);
        }
        while (!queue.isEmpty()) {
            TreeNode top = queue.poll();
            if (top != null) {
                //利用队列也可以放入null值来判断
                queue.offer(top.left);
                queue.offer(top.right);
            } else {
                break;
            }
        }
        //如果队列中存在非null的值,说明不是完全二叉树
        while (!queue.isEmpty()) {
            TreeNode top = queue.poll();
            if (top != null) {
                return false;
            }
        }
        return true;
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/41572.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux搭建node环境-MobaXterm+node+pm2安装

1.登录session 2.安装X11-forwarding 我也不知道这个有什么用&#xff0c;但是有个叉叉在那里有点难受&#xff0c;就把它解决了什么是X11-forwarding&#xff1f;怎么使用&#xff1f; yum install xorg-x11-xauth xorg-x11-fonts-* xorg-x11-font-utils xorg-x11-fonts-Ty…

如何将jar 包下载到自定义maven仓库

下载命令 mvn install:install-file -Dfileartifactid-version.jar -DgroupIdgroupid -DartifactIdartifactid -Dversionversion -Dpackagingjar -DlocalRepositoryPath. -DcreateChecksumtrue参数解释 在上述命令中&#xff0c;需要替换以下参数&#xff1a; artifactid-vers…

SQL中为何时常见到 where 1=1?

你是否曾在 SELECT 查询中看到过 WHERE 11 条件。我在许多不同的查询和许多 SQL 引擎中都有看过。这条件显然意味着 WHERE TRUE&#xff0c;所以它只是返回与没有 WHERE 子句时相同的查询结果。此外&#xff0c;由于查询优化器几乎肯定会删除它&#xff0c;因此对查询执行时间没…

cocosCreator 3.6以上接入腾迅Bugly 捕捉JS错误 Android

cocosCreator3.6以上接入Bugly上报其实很简单&#xff0c;不需要网上那么多弯弯绕&#xff0c;三须三步走。 1. 按照官网方式接入android的bugly 2. android端写一个Bugly上报管理类 3. 修改你工程目录下native\engine\common\Classes\目录下的Game.h, Game.cpp两个文件&…

基于python的爬虫实现

定义 爬虫&#xff08;Web crawler&#xff09;&#xff0c;也被称为网络爬虫、网络蜘蛛或网络机器人&#xff0c;是一种自动化程序&#xff0c;用于浏览互联网并收集网页内容。 基本原理 爬虫的工作原理是通过发送HTTP请求从网页服务器获取网页的内容&#xff0c;然后解析网…

计算机专升本基础笔记二 进制转换及二进制运算规则

进制转换及二进制运算规则 什么是进制&#xff1f;     进制就是进位计数制&#xff0c;是人为定义的带进位的计数方法。我们的时间就是六十进制(满60秒进一分钟&#xff0c;满60分钟进1小时&#xff09;&#xff1b;对于任何一种进制—X进制&#xff0c;就表示每一位上的数…

GUI-Menu菜单实例(颜色+线型菜单)

运行代码&#xff1a; //GUI-Menu菜单实例&#xff08;颜色线型菜单&#xff09; #include"std_lib_facilities.h" #include"GUI/Simple_window.h" #include"GUI/GUI.h" #include"GUI/Graph.h" #include"GUI/Point.h"struc…

Java的数据结构-Map集合

文章目录 Map概述Map常用方法Map遍历元素的方法1.方法一&#xff1a;keySet()2.方法二&#xff1a;entrySet() HashMap Map概述 1、Map和collection没有继承关系2、Map集合以key和value的方式存储数据&#xff1a;键值对key和value都是引用数据类型。key和value都是存储对象的…

【LocalSend】开源跨平台的局域网文件传输工具,支持IOS、Android、Mac、Windows、Linux

工作前提条件&#xff1a;设备使用相同的局域网。 LocalSend is a cross-platform app that enables secure communication between devices using a REST API and HTTPS encryption. Unlike other messaging apps that rely on external servers, LocalSend doesn’t require …

【网络安全】渗透测试工具——Burp Suite

渗透测试工具Burp Suite主要功能详解 前言一、 Proxy模块1.1 界面布局1.1.1 菜单栏&#xff08;1&#xff09; 菜单栏 Burp&#xff08;2&#xff09; 菜单栏 project&#xff08;3&#xff09; 菜单栏 Intruder&#xff08;4&#xff09; 菜单栏 Repeater&#xff08;5&#x…

C# Modbus通信从入门到精通(2)——Modbus RTU协议原理

Modbus RTU是串行链路上的协议,也就是说Modbus RTU是通过串口通信来实现的,它可以通过RS232、RS485物理层的接口来实现,同时它也是一个主从协议,在同一时间总线上只能有一个主站和一个或多个(最多247)个从站。Modbus通信总是由主站发起,从站没有接收到主站的请求时不会发…

Kubernetes轻量级日志工具Loki安装及踩坑记录

Loki简介 Loki是Grafana出品的一个轻量级日志系统&#xff0c;熟悉ELK的都知道ELK使用起来的成本&#xff0c;而且仅仅是日志检索使用ELK的话有点大材小用了。Loki8技术栈中使用了以下组件。 Promtail 用来将容器日志发送到 Loki 或者 Grafana 服务上的日志收集工具&#xff0c…

基于单片机的智能鞋柜的设计与实现

功能介绍 以51单片机作为主控系统&#xff1b;通过DHT11温湿度采集&#xff1b;通过按键设置逻辑处理&#xff1b;通过LED紫外线消毒&#xff1b;通过继电器控制风扇进行换气除湿&#xff1b;通过继电器控制加热片进行加热&#xff1b;整个电路以5v供电; 电路图 PCB 源代码 #i…

OSS对象存储后端实现+Vue实现图片上传【基于若依管理系统开发】

文章目录 基本介绍术语介绍图片上传方式介绍普通上传用户直传应用服务器签名后直传 OSS对象存储后端实现maven配置文件配置类ServiceController 图片上传前端图片上传组件api页面使用组件组件效果 基本介绍 术语介绍 Bucket&#xff08;存储空间&#xff09;&#xff1a;用于…

7-Spring cloud之路由网关zuul

7-Spring cloud之路由网关zuul 1. 前言2. 关于zuul2.1 zuul基本原理2.2 为什么要使用zuul 3. 搭建zuul3.1 项目结构3.2 基本配置3.2.1 pom文件3.2.2 yml文件3.3.3 启动类 3.3 测试看效果3.3.1 演示3.3.1 架构图 4. zuul路由访问映射规则4.1 映射服务提供者的服务名4.2 访问加前…

基于vue3+pinia2仿ChatGPT聊天实例|vite4.x仿chatgpt界面

原文&#xff1a;基于vue3pinia2仿ChatGPT聊天实例|vite4.x仿chatgpt界面 基于vue3pinia2仿ChatGPT聊天实例|vite4.x仿chatgpt界面 使用vue3pinia2开发仿制chatgpt界面聊天实例Vue3-Chatgpt 基于Vue3.xPinia2VueRouterVue3-Markdown等技术构建仿ChatGPT网页端聊天程序。支持经…

《动手学深度学习》(pytorch版本)中`d2lzh_pytorch`包问题

《动手学深度学习》&#xff08;pytorch版本&#xff09;中d2lzh_pytorch包问题

Redis安装与配置指南:适用于Windows、Mac和Linux系统的详细教程

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…

opencv-07-感兴趣区域(ROI)

在图像处理过程中&#xff0c;我们可能会对图像的某一个特定区域感兴趣&#xff0c;该区域被称为感兴趣区 域&#xff08;Region of Interest&#xff0c;ROI&#xff09;。在设定感兴趣区域 ROI 后&#xff0c;就可以对该区域进行整体操作。 以下是一些 OpenCV ROI应用场景 …

华为认证的题库,不仅能考试,还能帮你提升技能

1、OSPF协议在哪种状态下确定DD报文的主从关系&#xff1f; A. 2-way B.Exchange C. ExStart D. Full 2、在VRP操作系统中&#xff0c;如何进入OSPF区域0的视图&#xff1f;A. [Huawei-ospf-1]area 0 B.[Huawei]ospf area 0 C. [Huawei-ospf-1]area 0 enable D. [Huawe…