【Java数据结构】二叉树

1.树型结构

1.1树的概念

        树是一种非线性的数据结构,由n个结点组成的具有层次关系的集合。下面是它的特点:

  • 根结点是没有前驱的结点(没有父结点的结点)
  • 子结点之间互不相交
  • 除了根结点外,其它结点都只有一个父结点
  • n个结点有n-1条边

下面介绍一些常见的概念:

  • 结点的度:该结点有多少子节点,度就为几
  • 树的度:一个树中每个结点度中最大的那个就是树的度
  • 叶子结点:度为0的结点(不唯一)
  • 根结点:没有前驱的结点(也就是没有父结点的结点)
  • 双亲结点(父结点):该结点的父结点(唯一)
  • 孩子结点(子结点):该结点的子结点(不唯一)
  • 结构的层次:从根结点为第一层,往后数

下面这些就是了解即可

  • 树的高度:有几层树就有多高
  • 非终端结点(分支节点):除根结点和叶子结点外的结点
  • 兄弟结点:相同父结点之间称兄弟
  • 堂兄弟结点:父结点在同一层但不是同一个的结点之间称为堂兄弟
  • 结点的祖先:在一棵树上,根结点是所有结点的祖先
  • 子孙:该结点为根,往后层数与它相关的结点都是它的子孙
  • 森林:由m个互不相交的树组成的就是森林

1.2树的表现形式

        树的表现形式分多种,如双亲表示法、孩子表示法、孩子双亲表示法、孩子兄弟表示法等等,常用的就是孩子兄弟表示法。

2.二叉树 

2.1二叉树的概念

         一颗二叉树是结点的一个有限集合, 其中二叉树不存在度大于2的结点,并且二叉树的左子树和右子树是不能互换的,空树也是二叉树

2.2特殊二叉树

  • 满二叉树:满二叉树就是每层的结点数都达到该层最大值。如果由k层,那么结点总数就是2^(k-1);
  • 完全二叉树:完全二叉树就是假设有k层,其k-1层中每一层都是满的,在第k层中必须要从左到右依次放结点,如果中间出现空那么就不是二叉树;

 

2.3二叉树的性质

  1. 第i层上最多有2^(i-1)个结点;
  2. 深度为k的二叉树最大结点数为2^k-1(将每一层的结点数相加=>等比数列求和);
  3. 叶子结点有n0个,度为2的结点有n2个,就会出现n0 = n2 + 1这个式子;
  4. n个结点的完全二叉树的深度k为log (n+)向上取整;
  5. n个结点的二叉树,从上到下,从左到右排序。(1)已知父结点下标为i,求孩子结点下标。左孩子下标:(2*i)+1;右孩子下标:(2*i)+2 ;(2)已知孩子结点下标i,求父结点下标。父结点下标:(i-1)/2;

下面是一些关于二叉树性质的题目: 

由于度为0的结点数等于度为2的结点数加1,题目已知度为2的结点数就可以得到度为0的结点数,所以答案选B。

如果总结点数为偶数,那么度为1的结点个数是1个;如果结点为奇数,那么度为1的结点个数为0,再根据n0 =  n2 + 1,就可以求出叶子结点个数,所以答案选A。

由于log (n+1) 向上取整就是这个二叉树的高度,2^9 = 512 < 531 < 2^10 = 1024,所以答案选B。

2.4二叉树的存储

二叉树的存储分顺序存储和类似于链表的链式存储,现在主要讲解链式存储。

        链式存储是将一个一个结点连起来,一个结点有数据域和引用域(可多个),每个表示法的引用域都不是一样的,举一个例子:

// 孩子表示法
class Node {int val; // 数据域Node left; // 左孩子的引用Node right; // 右孩子的引用
}

 2.5二叉树的创建(简单型)

        首先和之前的线性表一样,使用内部类创建结点,然后再创建二叉树对应的结点个数,然后再将它们串连成二叉树,下面是孩子表示法结点创建: 

public class BrinaryTree {static class Node{public char val;public Node left;public Node right;public Node(char val){this.val = val;}}//创建二叉树public Node creatTree(){Node A = new Node('A');Node B = new Node('B');Node C = new Node('C');Node D = new Node('D');Node E = new Node('E');Node F = new Node('F');Node G = new Node('G');Node H = new Node('H');A.left = B;A.right = C;B.left = D;B.right = E;C.left = F;C.right = G;E.right = H;return A;}

 2.6二叉树的遍历

        以上是三种遍历,如果只是想要了解如何遍历而不是想通过常规手段得到答案的话,上面的方法就是最简单的理解方式。如果是前序遍历首先在结点左边(也可以称结点前面)做一个记号;如果是中序遍历首先在结点下面(也可以称结点中间)做一个记号;如果是后序遍历首先在结点右边(也可以称结点后面)做一个记号,然后从根结点的左边开始,围绕二叉树外延走一圈,最后到的根结点的右边为结束,在这过程中接触记号的顺序就是遍历的结果。

如果是按照常规思路来讲,就是什么遍历根结点就在哪个位置。比如前序遍历就是根左右,中序遍历就是左根右,后序遍历就是左右根。如果这个结点又是左结点又是根结点,那就根结点,其它的情况一样的。

下面我们用代码来实现这些遍历: 

  • 前序遍历

不管如何第一步都是判断这棵树是否为空,然后就是打印该根结点,然后用递归将根结点的左边的树遍历一遍,再用递归把根结点右边的树遍历一遍。下面是一棵二叉树的代码及遍历过程:

public void preOrder(Node root){if(root == null)return ;System.out.print(root.val+"  ");preOrder(root.left);preOrder(root.right);}

前序遍历返回链表结构

如果是返回一个链表结构,那就要利用返回的链表实现遍历,看图更能直观理解意思以及代码。(理解前序后,中序后序都是一个道理)

    public List<Node> preOrder2(Node root){List<Node> ret = new ArrayList<>();if (root == null)return ret;ret.add(root);List<Node> Left = preOrder2(root.left);ret.addAll(Left);List<Node> Right = preOrder2(root.right);ret.addAll(Right);return ret;}
  •  中序遍历

中序遍历道理差不多,开始也是判断是否为空,然后通过递归遍历根结点左边的树,再打印根结点,最后再递归遍历根结点右边的树。

    public void inOrder(Node root){if (root == null)return;inOrder(root.left);System.out.print(root.val+"  ");inOrder(root.right);}

中序遍历返回链表结构

    public List<Node> inOrder2(Node root) {List<Node> ret = new ArrayList<>();if (root == null)return ret;List<Node> leftTree = inOrder2(root.left);ret.addAll(leftTree);ret.add(root);List<Node> rightTree = inOrder2(root.right);ret.addAll(rightTree);return ret;}
  • 后序遍历

后序遍历也是一样道理,只是换成了左右根,先根遍历结点左边的树,然后遍历根结点右边的树,最后在打印。

    public void postOrder(Node root){if (root == null)return ;postOrder(root.left);postOrder(root.right);System.out.print(root.val+"  ");}

  后序遍历返回链表结构

    public List<Node> postOrder2(Node root) {List<Node> ret = new ArrayList<>();if (root == null)return ret;List<Node> leftTree = postOrder2(root.left);ret.addAll(leftTree);List<Node> rightTree = postOrder2(root.right);ret.addAll(rightTree);ret.add(root);return ret;}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

学习threejs,导入AWD格式的模型

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️THREE.AWDLoader AWD模型加…

Chapter4.3:Implementing a feed forward network with GELU activations

4 Implementing a GPT model from Scratch To Generate Text 4.3 Implementing a feed forward network with GELU activations 本节即将实现子模块&#xff0c;用于transformer block&#xff08;变换器块&#xff09;的一部分。为此&#xff0c;我们需要从激活函数开始。 深…

弥散张量分析开源软件 DSI Studio 简体中文汉化版可以下载了

网址&#xff1a; (63条消息) DSIStudio简体中文汉化版(2022年7月)-算法与数据结构文档类资源-CSDN文库

【信号滤波 (补充)】二阶陷波滤波代码推导过程(C++)

目录 二阶陷波滤波器计算实例一、 传递函数的参数推导1. 首先 b 0 , b 1 , b 2 b_0, b_1, b_2 b0​,b1​,b2​是怎么推导出来的&#xff1f;2. 带入实际值求解3. 验证上述的传递函数 二、将传递函数转化成差分方程2.1 传递函数写成输入输出形式2.2 Z域转化为时域 三、将差分方程…

C++进阶——用Hash封装unordered_map和unordered_set

目录 前言 源码怎么说 为什么要兼容&#xff1f; 兼容的具体做法&#xff1f; 为什么要把Key转为整数&#xff08;HashFcn&#xff09;&#xff1f; 模拟实现 一、建立框架 二、迭代器 运算符重载 迭代器兼容大法 三、[ ]重载 四、实现不能修改key 实现及测试代码 …

安装MySQL的五种方法(Linux系统和Windows系统)

一.在Linux系统中安装MySQL 第一种方法:在线YUM仓库 首先打开MySQL官网首页 www.mysql.com 找到【DOWNLOADS】选项&#xff0c;点击 下拉&#xff0c;找到 【MySQL Community(GPL) Downloads】 在社区版下载页面中&#xff0c;【 MySQL Yum Repository 】链接为在线仓库安装…

极客说|微软 Phi 系列小模型和多模态小模型

作者&#xff1a;胡平 - 微软云人工智能高级专家 「极客说」 是一档专注 AI 时代开发者分享的专栏&#xff0c;我们邀请来自微软以及技术社区专家&#xff0c;带来最前沿的技术干货与实践经验。在这里&#xff0c;您将看到深度教程、最佳实践和创新解决方案。关注「极客说」&am…

封装/前线修饰符/Idea项目结构/package/impore

目录 1. 封装的情景引入 2. 封装的体现 3. 权限修饰符 4. Idea 项目结构 5. package 关键字 6. import 关键字 7. 练习 程序设计&#xff1a;高内聚&#xff0c;低耦合&#xff1b; 高内聚&#xff1a;将类的内部操作“隐藏”起来&#xff0c;不需要外界干涉&#xff1b…

【C++】P5733 【深基6.例1】自动修正

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 &#x1f4af;前言&#x1f4af;题目描述&#x1f4af;解题思路概述&#x1f4af;第一种实现方式&#xff1a;直接使用字符ASCII值计算代码实现代码分析 &#x1f4af;第二种实现方式&#xff1a;直接修改…

【Elasticsearch】文档操作:添加、更新和删除

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;精通Java编…

【insert 插入数据语法合集】.NET开源ORM框架 SqlSugar 系列

系列文章目录 &#x1f380;&#x1f380;&#x1f380; .NET开源 ORM 框架 SqlSugar 系列 &#x1f380;&#x1f380;&#x1f380; 文章目录 系列文章目录一、前言 &#x1f343;二、插入方式 &#x1f4af;2.1 单条插入实体2.2 批量 插入实体2.3 根据字典插入2.4 根据 Dat…

权限掩码umask

1 、 设置新建文件或目录的默认权限 在 Linux 系统中&#xff0c;当用户创建一个新的文件或目录时&#xff0c;系统都会为新建的文件或目录分配默认的权限&#xff0c;该默认权限与umask 值有关&#xff0c;其具体关系是&#xff1a; 新建文件的默认权限 0666-umask 值 新建…

202-01-06 Unity 使用 Tip1 —— UnityHub 模块卸载重装

文章目录 1 卸载模块2 更新配置文件3 重启 UnityHub 起因&#xff1a; ​ WebGL 平台打包程序报错&#xff0c;懒得修复了&#xff0c;因此粗暴地删了重装。但是 UnityHub 不支持卸载模块&#xff0c;因此手动配置。 1 卸载模块 ​ 以 Unity 6000.0.26f1c1 为例&#xff0c;其…

打造三甲医院人工智能矩阵新引擎(二):医学影像大模型篇--“火眼金睛”TransUNet

一、引言 1.1 研究背景与意义 在现代医疗领域,医学影像作为疾病诊断与治疗的关键依据,发挥着不可替代的作用。从传统的X射线、CT(计算机断层扫描)到MRI(磁共振成像)等先进技术,医学影像能够直观呈现人体内部结构,为医生提供丰富的诊断信息,涵盖疾病识别、病灶定位、…

国产编辑器EverEdit - 两种删除空白行的方法

1 使用技巧&#xff1a;删除空白行 1.1 应用场景 用户在编辑文档时&#xff0c;可能会遇到很多空白行需要删除的情况&#xff0c;比如从网页上拷贝文字&#xff0c;可能就会存在大量的空白行要删除。 1.2 使用方法 1.2.1 方法1&#xff1a; 使用编辑主菜单 选择主菜单编辑 …

李宏毅机器学习笔记-Transformer

目录 1. Seq2seq 2. encoder Transformer 中的 Block 结构 3. Decoder 4.Encoder和Decoder间的信息传递 5.Training 6.Tips 1. Seq2seq Transformer 是一个seq2seq的model。Seq2seq指的是input是一个序列&#xff0c;输出也是一个序列&#xff0c;输出的长度是由机器自己…

GitLab集成Runner详细版--及注意事项汇总【最佳实践】

一、背景 看到网上很多用户提出的runner问题其实实际都不是问题&#xff0c;不过是因为对runner的一些细节不清楚导致了误解。本文不系统性的介绍GitLab-Runner&#xff0c;因为这类文章写得好的特别多&#xff0c;本文只汇总一些常几的问题/注意事项。旨在让新手少弯路。 二、…

指针 const 的组合

1、首先来了解一下常量 const int num 5&#xff1b; 那么num的值是5&#xff0c; num的值不可修改 2、来了解一下指针 int value 5; int* p &value; 我喜欢吧指针和类型放一起&#xff0c;来强调p是一个指针类型&#xff0c; 而赋值的时候就得赋值一个int类型的地址…

《C++11》各种初始化方式的详细列举与对比

在 C 中&#xff0c;初始化对象的方式多种多样。随着 C 标准的演进&#xff0c;特别是 C11 的引入&#xff0c;初始化方式得到了显著的扩展和改进。本文将详细列举 C 中的各种初始化方式&#xff0c;并对它们进行对比&#xff0c;帮助开发者更好地理解和应用这些特性。 1. C98…

前端小案例——520表白信封

前言&#xff1a;我们在学习完了HTML和CSS之后&#xff0c;就会想着使用这两个东西去做一些小案例&#xff0c;不过又没有什么好的案例让我们去练手&#xff0c;本篇文章就提供里一个案例——520表白信封 ✨✨✨这里是秋刀鱼不做梦的BLOG ✨✨✨想要了解更多内容可以访问我的主…