数据结构之初始二叉树(2)

找往期文章包括但不限于本期文章中不懂的知识点:

个人主页:我要学编程(ಥ_ಥ)-CSDN博客

所属专栏:数据结构(Java版)

二叉树的前置知识(概念、性质、、遍历)

通过上篇文章的学习,我们已经知道什么是二叉树,以及其性质和遍历的方式了。接下来主要是实现代码。

目录

伪创建二叉树

遍历二叉树 

获取二叉树中节点的个数 

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

获取二叉树中第K层节点的个数

获取二叉树的高度 

在二叉树中找寻元素 


伪创建二叉树

为啥叫伪创建二叉树呢?因为我们现在才刚开始学习二叉树,而创建二叉树是一个非常复杂的过程(树的递归定义的)。因此我们就先手动的来创建二叉树。树是有一个一个的结点组成,因此得先把结点创建出来。树的结点我们采用的是简单的孩子表示法:

    // 树的结点static class TreeNode {public char val; // 数据域public TreeNode left; // 左子树public TreeNode right; // 右子树public TreeNode(char val) {this.val = val;}}

创建的二叉树图形如下:

    public TreeNode createBinaryTree() {TreeNode A = new TreeNode('A');TreeNode B = new TreeNode('B');TreeNode C = new TreeNode('C');TreeNode D = new TreeNode('D');TreeNode E = new TreeNode('E');TreeNode F = new TreeNode('F');TreeNode G = new TreeNode('G');// 根据图形关系把结点之间相连A.left = B;A.right = C;B.left = D;B.right = E;C.left = F;C.right = G;// 返回根结点return A;}

遍历二叉树 

二叉树创建完成后,我们就可以遍历打印二叉树,看看是否符合我们的预期结果。遍历的四种方式,我们前面也学习了。

前序遍历: 

    // 前序遍历public void preOrder(TreeNode root) {if (root == null) {return;}// 打印根结点的值System.out.print(root.val+" ");// 递归遍历根的左子树preOrder(root.left);// 递归遍历根的右子树preOrder(root.right);}

递归的限制条件:当递归到 root 为 null 时,就开始回退。随着递归的深入,root 不断的接近 null。

中序遍历:

    // 中序遍历public void inOrder(TreeNode root) {// 中序遍历:左子树->根->右子树if (root == null) {return;}// 递归遍历根的左子树inOrder(root.left);// 打印根结点的值System.out.print(root.val+" ");// 递归遍历根的右子树inOrder(root.right);}

后序遍历:

    // 后序遍历public void postOrder(TreeNode root) {// 后序遍历:左子树->右子树->根if (root == null) {return;}// 递归遍历根的左子树postOrder(root.left);// 递归遍历根的右子树postOrder(root.right);// 打印根结点的值System.out.print(root.val+" ");}

由于层序遍历还是比较复杂,因此我们后面再学习。

获取二叉树中节点的个数 

思路一:这个同样是遍历二叉树,遇到不为空的结点就++,最后统计的就是树的节点个数。

    // 记录节点个数public int treeNodeSize; public void size(TreeNode root) {if (root == null) {return;}// 根结点treeNodeSize++;// 左子树size2(root.left);// 右子树size2(root.right);}

思路二:整棵树的节点个数等于 根结点+左子树的节点个数+右子树的节点个数

    // 获取树中节点的个数public int size(TreeNode root) {if (root == null) {return 0;}// 左子树的节点个数+右子树的节点个数+根结点return size(root.left)+size(root.right)+1;}

思路一采用的是遍历的方式,思路二采用的是化为子问题的方式。思路二也是更加接近递归的方式。

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

思路:首先,我们得知道什么是叶子节点。叶子结点的特点是其左孩子和右孩子都是null。同样这也是采用遍历的方式。

法一:采用子问题思路

    // 获取叶子节点的个数public int getLeafNodeCount(TreeNode root) {if (root == null) {return 0;}// 遇到叶子结点就返回1if (root.left == null && root.right == null) {return 1;}// 返回左子树的叶子节点个数+右子树的叶子节点个数return getLeafNodeCount(root.left) + getLeafNodeCount(root.right);}

法二:采用遍历思路

    public int leafSize;public void getLeafNodeCount(TreeNode root) {if (root == null) {return;}if (root.left == null && root.right == null) {leafSize++;}// 遍历左子谁getLeafNodeCount2(root.left);// 遍历右子树getLeafNodeCount2(root.right);}

获取二叉树中第K层节点的个数

上面是对于第K层的介绍,根结点是作为第一层。 

思路:当K为1时,就可以直接返回这一层的节点个数即可。因此我们就是要递归到K不断的接近1.

法一: 采用子问题思路

    // 获取第K层节点的个数public int getKLevelNodeCount(TreeNode root, int k) {// 假定不存在K无效的情况if (root == null) {return 0;}if (k == 1) {return 1;}// 左子树的第k-1层的节点个数+右子树的第k-1层的节点个数return getKLevelNodeCount(root.left, k-1) +getKLevelNodeCount(root.right, k-1);}

法二: 采用遍历思路

    public int getLevelNodeSize;public void getKLevelNodeCount(TreeNode root, int k) {// 假定不存在K无效的情况if (root == null) {return;}if (k == 1) {getLevelNodeSize++;}// 遍历左子树的第k-1层getKLevelNodeCount2(root.left, k-1);// 遍历右子树的第k-1层getKLevelNodeCount2(root.right, k-1);}

获取二叉树的高度 

思路:获取二叉树的高度和求第K层节点的个数类似。同样根结点算高度为1。接着就是分别递归计算左子树和右子树的高度的最大值。

采用子问题思路

    // 获取二叉树的高度public int getHeight(TreeNode root) {if (root == null) {return 0;}// 左子树与右子树的最大高度+根结点return Math.max(getHeight(root.left), getHeight(root.right)) + 1;}

这个如果不采用子问题思路,而是用遍历思路的话,只能用层序遍历来写,又因为层序遍历过于复杂,因此我们暂时先不写这个代码。

在二叉树中找寻元素 

 思路:这个比较简单,就是遍历去比较即可。

    // 检测值为value的元素是否存在public TreeNode find(TreeNode root, int val) {if (root == null) {return null;}// 采用前序遍历的方式:根->左子树->右子树// 根if (root.val == val) {return root;}// 在左子树中寻找,肯定有一个结果TreeNode findLeft = find(root.left, val);// 如果不为null,则说明找到了if (findLeft != null) {return findLeft;}// 在右子树中寻找,肯定有一个结果,不管结果如何直接返回即可return find(root.right, val);}

注意:这里在寻找二叉树中的节点时,采用前序遍历的方式是最有效率的。因为前序遍历是首先比较根结点,而我们就是需要比较根结点。 

对于二叉树的基本操作我们就已经学习完了。基于上述基本操作就可以进行一些简单的刷题了,后续也会在刷题中继续完善二叉树的相关操作。

好啦!本期 数据结构之初始二叉树(2)的学习之旅就到此结束啦!我们下一期再一起学习吧!

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

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

相关文章

iOS——MRC与ARC以及自动释放池深入底层学习

MRC与ARC再回顾 在前面,我们简单学了MRC与ARC。MRC指手动内存管理,需要开发者使用retain、release等手动管理对象的引用计数,确保对象在必要时被释放。ARC指自动内存管理,由编译器自动管理对象的引用计数,开发者不需要…

如何用EXCEL自动解方程/方程组?利用 矩阵乘法X=A-*B,X=mmult(minverse(A), B)

目录 问题的由来 1 数据 → 模拟分析 → 单变量求解 1.1 找一个单元格填入公式 1.2 功能入口 1.3 选择单变量求解,分别填入内容 1.4 求解 1.5 这个感觉用处不大 2 重点介绍,用EXCEL进行矩阵运算解方程的操作 2.1 运用EXCEL进行矩阵运算&…

Sentinel-1 Level 1数据处理的详细算法定义(四)

《Sentinel-1 Level 1数据处理的详细算法定义》文档定义和描述了Sentinel-1实现的Level 1处理算法和方程,以便生成Level 1产品。这些算法适用于Sentinel-1的Stripmap、Interferometric Wide-swath (IW)、Extra-wide-swath (EW)和Wave模式。 今天介绍的内容如下: Sentinel-1 L…

操作系统内核源码杂谈篇:临界区

临界资源,是指同一时刻只能由一个线程(linux下为进程)访问的资源,而临界区就是为了确保临界资源访问是单一数据流。 临界区的代码执行,也就是进行原子操作,不会被打断。 先分析RTOS的运行架构&#xff0c…

人工智能算法工程师(高级)课程1-单类目标识别之人脸检测识别技术MTCNN模型介绍与代码详解

大家好,我是微学AI,今天给大家介绍一下人工智能算法工程师(高级)课程1-单类目标识别之人脸检测识别技术MTCNN模型介绍与代码详解。本文深入探讨了基于PyTorch的人脸检测与识别技术,详细介绍了MTCNN模型、Siamese network以及center loss、sof…

qml 实现一个listview

主要通过qml实现listvie功能&#xff0c;主要包括右键菜单&#xff0c;滚动条&#xff0c;拖动改变内容等&#xff0c;c 与 qml之间的变量和函数的调用。 main.cpp #include <QQuickItem> #include <QQmlContext> #include "testlistmodel.h" int main…

Java里的引用详解

1.体验方法引用 方法引用的出现原因 在使用Lambda表达式的时候&#xff0c;我们实际上传递进去的代码就是一种解决方案&#xff1a;拿参数做操作 那么考虑一种情况&#xff1a;如果我们在Lambda中所指定的操作方案&#xff0c;已经有地方存在相同方案&#xff0c;那是否还有必要…

PHP房产中介租房卖房平台微信小程序系统源码

​&#x1f3e0;【租房卖房新选择】揭秘房产中介小程序&#xff0c;一键搞定置业大事&#xff01;&#x1f3e1; &#x1f50d;【开篇&#xff1a;告别繁琐&#xff0c;拥抱便捷】&#x1f50d; 还在为找房子跑断腿&#xff1f;为卖房发愁吗&#xff1f;今天给大家安利一个超…

JavaScript 获取 url(get)参数

https://andi.cn/page/621584.html

pytorch学习(八)Dataset加载分类数据集

我们之前用torchvision加载了pytorch的网络数据集&#xff0c;现在我们用Dataset加载自己的数据集&#xff0c;并且使用DataLoader做成训练数据集。 图像是从网上下载的&#xff0c;网址是 点这里&#xff0c;标签是图像文件夹名字。下载完成后作为自己的数据集。 1.加载自己…

PyTorch 深度学习实践-循环神经网络基础篇

视频指路 参考博客笔记 参考笔记二 文章目录 上课笔记基于RNNCell实现总代码 基于RNN实现总代码 含嵌入层的RNN网络嵌入层的作用含嵌入层的RNN网络架构总代码 其他RNN扩展基本注意力机制自注意力机制&#xff08;Self-Attention&#xff09;自注意力计算多头注意力机制&#xf…

RPC与服务的注册发现

文章目录 1. 什么是远程过程调用(RPC)?2. RPC的流程3. RPC实践4. RPC与REST的区别4.1 RPC与REST的相似之处4.2 RPC与REST的架构原则4.3 RPC与REST的主要区别 5. RPC与服务发现5.1 以zookeeper为服务注册中心5.2 以etcd为服务注册中心 6. 小结参考 1. 什么是远程过程调用(RPC)?…

TCP三次握手与四次挥手详解

1.什么是TCP TCP&#xff08;Transmission Control Protocol&#xff0c;传输控制协议&#xff09;是一种面向连接的、可靠的、基于字节流的通信协议&#xff0c;属于互联网协议族&#xff08;TCP/IP&#xff09;的一部分。TCP 提供可靠的、顺序的、无差错的数据传输服务&…

win11家庭版怎么升级专业版

随着Windows 11的推出&#xff0c;许多用户享受到了全新的用户界面和功能。然而&#xff0c;Windows 11家庭版在某些高级功能上有所限制&#xff0c;例如&#xff0c;组策略管理、远程桌面连接等。为了满足更多的工作需求&#xff0c;许多用户希望将Windows 11家庭版升级到专业…

十、Java集合 ★ ✔(模块18-20)【泛型、通配符、List、Set、TreeSet、自然排序和比较器排序、Collections、可变参数、Map】

day05 泛型,数据结构,List,Set 今日目标 泛型使用 数据结构 List Set 1 泛型 1.1 泛型的介绍 ★ 泛型是一种类型参数&#xff0c;专门用来保存类型用的 最早接触泛型是在ArrayList&#xff0c;这个E就是所谓的泛型了。使用ArrayList时&#xff0c;只要给E指定某一个类型…

分布式IO系统BL201 Profinet耦合器

BL201耦合器是一个数据采集和控制系统&#xff0c;基于强大的32 位微处理器设计&#xff0c;采用Linux操作系统&#xff0c;是一种模块化的分布式I/O系统。该系统由3部分组成&#xff1a;现场总线耦合器和各种类型的&#xff08;数字和模拟信号以及特殊功能&#xff09;I/O模块…

Keka for Mac v1.4.3 中文下载 解压/压缩工具

Mac分享吧 文章目录 效果一、下载软件二、开始安装1、双击运行软件&#xff0c;将其从左侧拖入右侧文件夹中&#xff0c;等待安装完毕2、应用程序显示软件图标&#xff0c;表示安装成功 三、运行测试1、打开软件2、文件访问权限修改3、访达扩展 安装完成&#xff01;&#xff…

Ubantu 使用 docker 配置 + 远程部署 + 远程开发

大家好我是苏麟 , Ubantu 一些配置 . 视频 : 服务器很贵&#xff1f;搞台虚拟机玩玩&#xff01;保姆级 Linux 远程开发教程_哔哩哔哩_bilibili Docker安装及配置 安装命令 : sudo apt install docker.io 查看版本号 : docker -v 查看虚拟机地址命令 : ifconfig 虚拟机地址 或…

【Android】 dp与sp,加冕为王

目录 重要概念 屏幕尺寸 屏幕分辨率 屏幕像素密度 基础知识&#xff1a; ppi pt DPI 的定义和重要性 Android 中的 DPI 级别 px dp&#xff08;Density Independent Pixels&#xff09; sp&#xff08;Scale-independent Pixels&#xff09; 安卓的dp/dip、sp 虚拟…

PlantUML-UML 绘图工具安装、Graphviz安装、本地使用/在线使用、语法、图示案例

文章目录 前言本地安装vscode安装插件下载安装Graphviz配置Graphviz环境变量测试 在线使用演示PlantUML语法总结活动图&#xff08;新语法&#xff09;时序图类图用例图其他图 更多相关内容可查看 前言 本篇提供两种使用方式分别为 在线使用地址1&#xff1a;https://www.pla…