JAVA 二叉树超详解(1)

树形结构

概念

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

1.有一个特殊的结点,称为根结点,根节点没有前驱节点

2.除根节点外,其余节点被分成M(M>0)个互不相交的集合T1,T2.....Tm,其中每一个集合Ti又是一棵与树类似的子树。每棵子树的根节点有且只有一个前驱,可以有0或者多个后继(一棵树是由若干不相交的子树构成)

3.树是递归定义的

注意:树形结构中,子树之间不能有交集,否则就不是树形结构 

判断树与非树的重要考察点:

1.子树是不想交的

2.除了跟节点外,每个节点有且仅有一个父节点

3.一棵N个节点的树有N-1条边

关键词

以下图为例:

节点的度:一个结点含有子树的个数称为结点的度; 如上:A的度为6

树的度:一棵树中,所有结点的度的最大值称为树的度;如上:树的度为6

叶子节点或终端节点:度为零的结点称为叶节点;如上:B,C,H,I,P等为叶子节点

孩子结点或子节点:一个节点含有的子树的根节点称为该结点的子节点;如:B是A的子节点

根结点:一棵树中,没有双亲结点的结点,如上:A为根结点

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

树的表示形式

树结构相对于线性表就比较复杂了,要存储表示起来就比较麻烦了,实际中树有很多表示方式,如:双亲表示法,孩子表示法,孩子双亲表示法等等。我们就来简单了解一下最常用的孩子兄弟表示法(通过一个结点的一个孩子去找它其它的子节点(这个孩子的兄弟))。

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

简图:

树的应用

文件系统管理(目录和文件)

 

二叉树

概念

一棵二叉树是结点的一个有限集合,该集合:

 1.或者为空

2.或者是由一个根节点加上两棵分别被称为左子树和右子树的二叉树组成。

 

其中:A为根节点,B及其以下的部分为根结点的左子树,C及其以下的部分为根节点的右子树。

从上图可以看出:

1.二叉树不存在度大于2的结点

2.二叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序树 

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

 

两种特殊的二叉树

1.满二叉树:一棵二叉树,如果每层的节点数都达到最大值,则这棵二叉树就是满二叉树。也就是说,如果一棵二叉树的层数为k,且节点总数2^K-1,那么他就是满二叉树。

2.完全二叉树:完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引来的。对于深度为K 的,有N个结点的二叉树,满二叉树中编号从0至N-1的结点--对应时称之为完全二叉树,也就是从左到右,从上到下依次存放结点的二叉树(其中一个为空就不是)要注意满二叉树是一种特殊的完全二叉树

二叉树的性质(重要)

1.若规定根节点的层数为1,则一棵非空二叉树的第i层上最多有2^(i-1)(i>0)个结点 

2.若规定只有根节点的二叉树深度为1,则深度为K的二叉树所含最多节点数为(就是满二叉树):2^K - 1(K>=0) 

3.对于任何一棵二叉树,如果其叶节点个数为n0,度为二的结点个数为n2,则有n0 = n2 + 1

 

推理如下:

4.具有N个结点的完全二叉树的深度为log(n+1)向上取整,底数为2(可以借助第二点反推)

5.对于具有n个结点的完全二叉树,如果按照从上至下从左至右的顺序对所有节点从0开始编号,那么对序号为i的节点有

(1).若i>0,双亲序号:(i-1)/2;i = 0,i为根结点编号,无双亲结点

(2).若2i+1<n,左孩子序号:2i+1,否则无左孩子

(3).若2i+2<n,右孩子序号:2i+2,否则无右孩子

二叉树的存储

二叉树的存储结构分为:顺序存储和类似于链表的链式存储。

二叉树的链式存储是通过一个一个的结点引用起来的,常见的引用方式有二叉和三叉表示方式:

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

 

二叉树的基本操作

说明

在学习二叉树基本操作之前,需要创建一棵二叉树,然后才能学习其相关的基本操作。此处先创建一个简单的二叉树: 

public class BinaryTree {public static class BTNode {BTNode left;BTNode right;int value;BTNode(int value) {this.value = value;}}private BTNode root;public void createBinaryTree() {BTNode node1 = new BTNode(1);BTNode node2 = new BTNode(2);BTNode node3 = new BTNode(3);BTNode node4 = new BTNode(4);BTNode node5 = new BTNode(5);BTNode node6 = new BTNode(6);root = node1;node1.left = node2;node2.left = node3;node1.right = node4;node4.left = node5;node5.right = node6;}
}

注意:上述代码并不是创建二叉树的真正方式,真正创建二叉树的方式后续再讲。 

 二叉树的遍历

1.前中后序遍历

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

 

在遍历二叉树时,如果没有某种规定,每一个人都煮自家的粥,按照各个不同的遍历方法,难免会有些混乱,如果按照某种规则进行约定,则每一个人遍历二叉树的方法是相同的。 

如果规定N为根结点,L代表根结点的左子树,R代表根结点的右子树,则根据结点的先后次序有以下的遍历方式:

1.NLR:前序遍历--先访问根节点--根的左子树--根的右子树(先遇到哪个就先访问哪个)

2.LNR:中序遍历--先访问根的左子树--根节点--根的右子树(一直向左走,直到左边为空,然后回溯访问结点)

3.LRN:后序遍历--先访问根的左子树--根的右子树--根结点(将一个结点的左右子树走完,再访问结点)

代码(主要利用递归的方式):

//前序遍历
void preOrder(Noot root) {//访问到并进行对节点内容打印的操作System.out.print(root.value);//先对左子树进行递归preOrder(root.left);//后对右子树进行递归preOrder(root.right);
}//中序遍历
void inOrder(Noot root) {//先对左子树进行递归preOrder(root.left);//访问到并进行对节点内容打印的操作System.out.print(root.value);//后对右子树进行递归preOrder(root.right);
}//后序遍历
void postOrder(Noot root) {//先对左子树进行递归preOrder(root.left);//后对右子树进行递归preOrder(root.right);//访问到并进行对节点内容打印的操作System.out.print(root.value);
}

参考示例:

1.前序遍历:123456

2.中序遍历:321546

3.后序遍历:325641 

2.层序遍历

定义:除了先序遍历,中序遍历,后序遍历外,还可以对二叉树进行层序遍历。设二叉树的根节点所在的层数为1,层序遍历就是从所在的二叉树的根节点出发,进行从上到下,从左到右的遍历。

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

云原生Kubernetes:K8S集群list-watch机制与 pod调度约束

目录 一、理论 1.K8S的list-watch 机制 2.亲和性 二、实验 1. 指定调度节点 2.节点亲和性 3.亲和性和反亲和 三、问题 1.新生成pod一直为pending 2.如何一次性删除pod和deployment 3.pod亲和性资源报错 4.pod反亲和性资源报错 四、总结 一、理论 1.K8S的list-wat…

【操作系统】24王道考研笔记——第五章 IO管理

第五章 IO管理 一、IO设备 1.1 基本概念与分类 1.2 IO控制器 电子部件 IO控制器组成 值得注意的小细节&#xff1a;①一个I/O控制器可能会对应多个设备&#xff1b; ②数据寄存器、控制寄存器、状态寄存器可能有多个&#xff08;如&#xff1a;每个控制/状态寄存器对应一个…

Java流式编程的使用

流式编程的使用步骤 使用流式编程的步骤就是: 设置数据源, 设置数据处理的方式,设置收集结果的方式。 使用filter方法实现过滤条件 例子为下&#xff08;查询年龄大于18的用户&#xff09;: Testpublic void streamTest1() {List<Student> students Arrays.asList(ne…

在gazebo仿真环境中加载多个机器人

文章目录 前言一、基本概念1、xacro2、Gazebo 加载单个机器人模型 二、原先launch文件代码三、 修改launch文件加载多个机器人总结 前言 单个机器人的各项仿真实验都基本完成&#xff0c;也实现了远程控制&#xff0c;接下来主要对多机器人编队进行仿真实验&#xff0c;在进行…

【EI会议征稿】第三届计算机图形学、人工智能与数据处理国际学术会议 (ICCAID 2023)

第三届计算机图形学、人工智能与数据处理国际学术会议 2023 3rd International Conference on Computer Graphics, Artificial Intelligence and Data Processing (ICCAID 2023) 第三届计算机图形学、人工智能与数据处理国际学术会议&#xff08;ICCAID 2023&#xff09;将于…

14.抽象工厂模式

UML 代码 #include <iostream> #include <list> using namespace std;class AbstractProductA { public:virtual void showa() 0; }; class ProductA1:public AbstractProductA { public:virtual void showa(){cout << "我是A1" << endl;}…

短视频矩阵系统源代码开发搭建分享--代码开源SaaS

一、什么是短视频矩阵系统&#xff1f; 短视频矩阵系统是专门为企业号商家、普通号商家提供帐号运营从流量 到转化成交的一站式服务方案&#xff0c;具体包含&#xff1a;点赞关注评论主动私信 &#xff0c;评论区回复&#xff0c;自动潜客户挖掘&#xff0c;矩阵号营销&#x…

工具及方法 - 二进制编辑软件

之前介绍过用Notepad和VSCode进行二进制文件编辑。 很多通用型的文本编辑器都会集成二进制文件编辑功能&#xff0c;或者使用插件等形式扩展此项功能。比如vi/vim等工具。 而且&#xff0c;作为文本编辑、二进制文件编辑一类的工具&#xff0c;数量众多&#xff0c;各有特色。…

机器学习 day36(纯度)

熵 这些例子的纯度和熵如图所示&#xff0c;且左侧为熵函数图熵函数是判断某组数据是否纯度高的指标 熵函数公式如上图&#xff0c;底数为2仅为了使函数峰值为1&#xff0c;且设定0log(0)为0&#xff0c;但log(0)为无穷大

Swift SwiftUI 隐藏键盘

如果仅支持 iOS 15 及更高版本&#xff0c;则可以通过聚焦和取消聚焦来激活和关闭文本字段的键盘。 在最简单的形式中&#xff0c;这是使用 FocusState 属性包装器和 focusable() 修饰符完成的-第一个存储一个布尔值&#xff0c;用于跟踪第二个当前是否被聚焦。 Code struct C…

Python中统计单词出现的次数,包含(PySpark方法)

思路&#xff1a; 定义一个函数&#xff0c;使用open函数&#xff0c;将文本内容打开。 定义一个空字典和空列表&#xff0c;进行循环及条件判断操作def count_word(file_path):dict_data {} #定义一个空字典f open(file_path,"r",encoding"UTF-8")lis…

cadence - 在allegro中出报告(Padstack Usage Report)来辅助制作orcad原理图封装

文章目录 cadence - 在allegro中出报告(Padstack Usage Report)来辅助制作orcad原理图封装概述笔记做PCB封装出报告 - Padstack Usage Report做原理图封装END cadence - 在allegro中出报告(Padstack Usage Report)来辅助制作orcad原理图封装 概述 现在做封装, 还是手工弄. 在…

Hadoop-sqoop

sqoop 1. Sqoop简介及原理 简介&#xff1a; Sqoop是一款开源的工具,主要用于在Hadoop(Hive)与传统的数据库(mysq1.postgresql..)间进行数据的传递&#xff0c;可以将一个关系型数据库&#xff08;例如: MySQL ,Oracle ,Postgres等&#xff09;中的数据导进到Hadoop 的HDFS中&…

Java 函数式编程思考 —— 授人以渔

引言 最近在使用函数式编程时&#xff0c;突然有了一点心得体会&#xff0c;简单说&#xff0c;用好了函数式编程&#xff0c;可以极大的实现方法调用的解耦&#xff0c;业务逻辑高度内聚&#xff0c;同时减少不必要的分支语句&#xff08;if-else&#xff09;。 一、函数式编…

性能测试 —— Tomcat监控与调优:status页监控

Tomcat服务器是一个免费的开放源代码的Web 应用服务器&#xff0c;Tomcat是Apache 软件基金会(Apache Software Foundation)Jakarta 项目中的一个核心项目&#xff0c;由Apache、Sun 和其他一些公司及个人共同开发而成。 Tomcat是一个轻量级应用服务器&#xff0c;在中小型系统…

20230918使用ffmpeg将mka的音频转为AAC编码以便PR2023来识别

20230918使用ffmpeg将mka的音频转为AAC编码以便PR2023来识别 2023/9/18 20:58 ffmpeg -i 1.mka -acodec aac 1.mp4 ffmpeg -i 1.mka -vn -c:a aac 2.aac ffmpeg -i 1.mka -vn -c:a aac 2.MP4 ffmpeg mka 转 aacmp4 https://avmedia.0voice.com/?id42526 用ffmpeg将mka格式转化…

Mybatis学习笔记11 缓存相关

Mybatis学习笔记10 高级映射及延迟加载_biubiubiu0706的博客-CSDN博客 缓存:cache 缓存的作用:通过减少IO的方式,来提高程序的执行效率 Mybatis的缓存:将select语句的查询结果放到缓存(内存)当中,下一次还是这条select语句的话,直接从缓存中取,不再查数据库.一方面是减少了I…

【新版】系统架构设计师 - 案例分析 - 信息安全

个人总结&#xff0c;仅供参考&#xff0c;欢迎加好友一起讨论 文章目录 架构 - 案例分析 - 信息安全安全架构安全模型分类BLP模型Biba模型Chinese Wall模型 信息安全整体架构设计WPDRRC模型各模型安全防范功能 网络安全体系架构设计开放系统互联安全体系结构安全服务与安全机制…

Windows 基于Visual Studio 开发Qt 6 连接MySQL 8

前提条件&#xff1a; 1、Visual Studio 2022 社区版(免费版) 2、Qt-6.5.1版本 3、MySQL 8 Qt 6 配置MySQL 8 动态/静态连接库和MySQL 8 驱动。 libmysql.dll 和libmysql.lib是QT所需的动态和静态链接库&#xff1b;qsqlmysql.dll 和qsqlmysql.dll.debug是Qt所需的mysql驱…

C#通过重写Panel改变边框颜色与宽度的方法

在C#中,Panel控件是一个容器控件,用于在窗体或用户控件中创建一个可用于容纳其他控件的面板。Panel提供了一种将相关控件组合在一起并进行布局的方式。以下是Panel控件的详细使用方法: 在窗体上放置 Panel 控件: 在 Visual Studio 的窗体设计器中,从工具箱中拖动并放置一…