【数据结构】一文带你掌握二叉树的构造与应用

news2024/11/27 3:34:15

文章目录

    • 1. 构造二叉树
    • 2. 前序遍历
      • 2.1 前序遍历递归
      • 2.2 前序遍历非递归
    • 3. 中序遍历
      • 3.1 中序遍历递归
      • 3.2 中序遍历非递归
    • 4. 后序遍历
      • 4.1 后序遍历递归
      • 4.2 后序遍历非递归
    • 5. 层序遍历
    • 6. 节点个数
      • 6.1 所有节点个数
      • 6.2 获得叶子节点个数
    • 7. 检测值为value的元素是否存在
    • 8.总结

PS: 前面我们已经详细介绍了二叉树的概念以及二叉树的遍历的概念等,一些详细概念知识点可以在下面链接中的博客查看。本文主要需要使用代码自己实现二叉树及应用。
二叉树的概念及遍历

1. 构造二叉树

二叉树是由一个节点一个个连接而成的,每个节点最多连接两个节点,所以每个节点需要有一个数据元素和两个指向左右子树的指针,当没有左右子树时,可以为null。

public class MyTreeNode {
    public int val;
    public MyTreeNode left,right;
    public MyTreeNode(int val){
        this.val = val;
    }
    public MyTreeNode(){}
}    

因为编译器本身并不会自动构造二叉树,所以我们要编写程序来构造一个二叉树,并通过一个节点root记录根节点。

    //构造Tree
    public MyTreeNode root;
    public MyTreeNode createTree(){
        MyTreeNode node1 = new MyTreeNode(1);
        MyTreeNode node2 = new MyTreeNode(2);
        MyTreeNode node3 = new MyTreeNode(3);
        MyTreeNode node4 = new MyTreeNode(4);
        MyTreeNode node5 = new MyTreeNode(5);
        MyTreeNode node6 = new MyTreeNode(6);

        root = node1;
        node1.left = node2;
        node2.left = node3;
        node1.right = node4;
        node4.left = node5;
        node4.right = node6;
        return root;
    }

如图
接下来应用将围绕此树进行。
树

2. 前序遍历

前序遍历的遍历顺序:访问根结点—>根的左子树—>根的右子树。
遍历结果:123456

2.1 前序遍历递归

参数root是当前节点,如果为null说明已经到叶子节点,直接返回。否则,我们先输出当前节点的值,然后递归遍历左子树,最后递归遍历右子树。

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

2.2 前序遍历非递归

我们使用一个栈来辅助遍历。首先将根节点压入栈中,然后每次从栈中弹出一个节点,并输出它的值。如果该节点有右子树,我们就将右子树压入栈中,因为左子树后遍历,为了后遍历左子树,我们将左子树后入栈,所以先遍历右子树。如果该节点有左子树,我们就将左子树压入栈中,因为下一步要遍历左子树。这样,我们就依次访问了整个二叉树节点。

    //前序遍历非递归
    public void norPreOrder(MyTreeNode root){
        if(root == null){
            return;
        }
        Stack<MyTreeNode> stack = new Stack<>();
        stack.push(root);
        while(!stack.isEmpty()){
            MyTreeNode cur = stack.pop();
            System.out.print(cur.val + " ");
            if(cur.right != null){
                stack.push(cur.right);
            }
            if(cur.left != null){
                stack.push(cur.left);
            }
        }
    }

3. 中序遍历

根的左子树—>根节点—>根的右子树。
遍历结果:321546

3.1 中序遍历递归

用递归实现,先递归遍历左子树,遍历完后将节点值加入结果列表中,然后再递归遍历右子树。

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

3.2 中序遍历非递归

借助辅助栈实现非递归中序遍历,首先检查当前节点是否为空以及是否有左子节点,如果有则将节点入栈,并将当前节点指向左子节点,继续进入循环,直到左子树遍历完毕,然后将节点出栈并添加到结果列表中,将当前节点指向右子节点,继续遍历。

    //中序遍历非递归
    public void norInOrder(MyTreeNode root){
        if(root == null){
            return;
        }
        Stack<MyTreeNode> stack = new Stack<>();
        MyTreeNode curr = root;
        while(curr != null || !stack.empty()) {
            while (curr != null) {
                stack.push(curr);
                curr = curr.left;
            }
            curr = stack.pop();
            System.out.print(curr.val + " ");
            curr = curr.right;
        }
    }

4. 后序遍历

根的左子树—>根的右子树—>根节点。
遍历结果:325641

4.1 后序遍历递归

用递归实现后序遍历,先递归遍历左子树,然后递归遍历右子树,最后将当前节点的值添加到结果列表中。

    // 后序遍历递归
    public void postOrder(MyTreeNode root){
        if(root == null){
            return;
        }
        postOrder(root.left);
        postOrder(root.right);
        System.out.print(root.val + " ");
    }

4.2 后序遍历非递归

用辅助栈实现后序遍历,首先将根节点入栈,然后定义一个辅助栈,将根节点出栈并压入辅助栈中。然后依次将当前节点的左孩子和右孩子入栈,但先入右孩子再入左孩子,因为要保证左孩子后访问。重复这个过程直到栈为空,然后从辅助栈依次将节点的值添加到结果列表中。

	//后序遍历非递归
    public void norPostOrder(MyTreeNode root) {
        if (root == null) {
            return;
        }

        Stack<MyTreeNode> stack1 = new Stack<>();
        Stack<MyTreeNode> stack2 = new Stack<>();
        stack1.push(root);
        while (!stack1.isEmpty()) {
            MyTreeNode cur = stack1.pop();
            stack2.push(cur);
            if (cur.left != null) {
                stack1.push(cur.left);
            }
            if (cur.right != null) {
                stack1.push(cur.right);
            }
        }

        while (!stack2.isEmpty()) {
            System.out.print(stack2.pop().val + " ");
        }
    }

5. 层序遍历

从根节点一层一层的遍历,借助队列的先进先出的特性实现.

    //层序遍历
    public void levelOrder(MyTreeNode root){
        if(root == null){
            return;
        }
        Queue<MyTreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while(!queue.isEmpty()){
            MyTreeNode cur = queue.poll();
            System.out.print(cur.val + " ");
            if(cur.left != null){
                queue.offer(cur.left);
            }
            if(cur.right != null){
                queue.offer(cur.right);
            }
        }
    }

6. 节点个数

6.1 所有节点个数

直接递归,遍历整个树,递归一次加1.

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

6.2 获得叶子节点个数

利用递归直接遍历,左右节点为null,则为叶子节点,加1.

    // 获取叶子节点的个数
    //叶子个数
    static int countLeaf = 0;
    public int sizeLeaf(MyTreeNode root){
        if(root == null){
            return 0;
        }
        if(root.left == null && root.right == null){
            countLeaf++;
        }
        sizeLeaf(root.left);
        sizeLeaf(root.right);
        return countLeaf;
    }

7. 检测值为value的元素是否存在

遍历,寻找

    // 检测值为value的元素是否存在
    public MyTreeNode find(MyTreeNode root, int val) {
        if(root == null) {
            return null;
        }
        if(root.val == val){
            return root;
        }
        MyTreeNode left = find(root.left,val);
        if(left != null){
            return left;
        }
        MyTreeNode right = find(root.right,val);
        if(right != null){
            return right;
        }
        return null;
    }

8.总结

这些实现都是经典的,类似这种可太多,我们平常可以多刷刷题,提升自己的代码能力,这样也可以更好的提升自己的代码能力.
大家可以也关注我的刷题集,每周更新经典好题,瑞思拜!
数据结构刷题集

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

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

相关文章

数据库SQL2000最基本的安装和操作教程

Chengg0769 2012年 转载请保留以下版权来源 www.mis2erp.com http://blog.csdn.net/chengg0769 http://www.haojiaocheng.cc 题外话&#xff1a; 之前写了一个项目&#xff0c;因为是国企&#xff0c;各种文档都要给到他们。当时就写了一个简单的维护管理SQL2000的文档。这…

【2352. 相等行列对】

来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 描述&#xff1a; 给你一个下标从 0 开始、大小为 n x n 的整数矩阵 grid &#xff0c;返回满足 Ri 行和 Cj 列相等的行列对 (Ri, Cj) 的数目。 如果行和列以相同的顺序包含相同的元素&#xff08;即相等的数组&#…

DMBOK知识梳理for CDGA/CDGP——第四章 数据架构(附常考知识点)

关 注ghz“大数据食铁兽”&#xff0c;回复“知识点”获取《DMBOK知识梳理for CDGA/CDGP》常考知识点&#xff08;第四章 数据架构&#xff09; 第四章 数据架构 第四章是CDGA|CDGP考试的重点考核章节之一&#xff0c;分值占比高&#xff0c;知识点比较密集&#xff0c;重点…

CAN message 属性DLC和DataLength,极易混淆

&#x1f345; 我是蚂蚁小兵&#xff0c;专注于车载诊断领域&#xff0c;尤其擅长于对CANoe工具的使用&#x1f345; 寻找组织 &#xff0c;答疑解惑&#xff0c;摸鱼聊天&#xff0c;博客源码&#xff0c;点击加入&#x1f449;【相亲相爱一家人】&#x1f345; 玩转CANoe&…

STM32开发(CubeMX+HAL)——点灯(轮询、中断)

目录 1.CubeMX生成工程文件 2.点灯1——轮询 3.点灯2——中断 3.1CubeMX配置时钟 3.2中断和事件简介 3.3配置GPIO口 3.4使能中断 3.5配置工程 3.6中断函数编写 1.CubeMX生成工程文件 1.1新建工程 1.2输入STM32C8T6选择芯片 1.3双击芯片 1.4 选择System Core—SYS——…

DAY09_JQueryBootStrap实现省略号效果

目录 1 JQuery简介2 引入JQuery方式3 JS与JQ之间的转换4 选择器4.1 基本选择器4.2 层级选择器4.2.1 层级选择器相关方法 4.3 过滤选择器4.4 内容选择器4.5 可见选择器4.6 隐藏显示的相关方法4.7 属性选择器4.8 子元素选择器4.9 表单选择器 5 JQ中新增的遍历方式6 JQ中相关方法7…

vue解决浏览器中跳转新页面缓存上一页表单等内容方法

在工作中&#xff0c;有可能会遇到需要缓存页面或组件的功能。 情况1&#xff1a;比如在h5中有个一个50个表单&#xff0c;在填到第40个表单时&#xff0c;需要你去另一个新页面去选择列表项&#xff0c;然后把数据带回来。需要我们不仅把数据带回来还要保留前面已经填好的40个…

GIS地图:解读未知的地理空间之谜

在这个信息爆炸的时代&#xff0c;如何有效地理解和利用地理空间数据成为各行各业追求的目标。而GIS地图作为一种强大的工具&#xff0c;能够帮助我们连接世界的空间智慧。 GIS地图的魅力在于它能够将庞大的地理数据转化为直观、可视化的地图表达。通过GIS地图&#xff0c;我们…

管理平台|智慧工地将成为施工界的“扛把子”!

大家都知道&#xff0c;建筑业是一个安全事故频发的高危行业&#xff0c;特别在施工环节&#xff0c;由于施工现场人员复杂、环境混乱、地点分散、多工序交叉等现象&#xff0c;如何进行现场施工管理就显得格外重要。 但是&#xff0c;依赖于现场管理的施工模式总是存在着很多…

数据结构-图结构

图是最为复杂的数据结构。如果数据元素之间存在一对多或者多对多的关系&#xff0c;那么这种数据的组织结构就叫作图结构。 图的基本概念 图的定义 图Graph是由顶点&#xff08;图中的节点被称为图的顶点&#xff09;的非空有限集合V与边的集合E&#xff08;顶点之间的关系&a…

什么AC+AP组网?什么是mesh组网?

一、什么是ACAP组网&#xff1f; ACAP组网是一种基于集中式管理的无线局域网&#xff08;WLAN&#xff09;组网架构&#xff0c;主要由AC&#xff08;Access Controller&#xff09;和多个AP&#xff08;Access Point&#xff09;组成。AC作为网络管理中心&#xff0c;负责控制…

别乱分层,PO、VO、DAO、BO、DTO、POJO 到底应该用在哪里,你知道吗

一、PO :&#xff08;persistant object&#xff09;&#xff0c;持久对象 二、VO :&#xff08;value object&#xff09;&#xff0c;值对象 三、DAO :&#xff08;Data Access Objects&#xff09;&#xff0c;数据访问对象接口 四、BO :&#xff08;Business Object&…

30天从入门到精通TensorFlow1.x 第六天,可视化工具 TensorBoard

文章目录 一、接前一天二、TensorBoard&#xff08;1&#xff09;. 什么是TensorBoard&#xff08;2&#xff09;. TensorBoard有什么用&#xff08;3&#xff09;. TensorBoard怎么安装 三、tf.summary模块&#xff08;1&#xff09;.如何使用tensorboard&#xff08;2&#x…

数据结构之二叉树(Binary Tree)详解

目录 1、什么是二叉树&#xff1f; 2、二叉树的遍历&#xff1a;深度优先和广度优先 &#xff08;1&#xff09;深度优先搜索(DFS)算法 &#xff08;2&#xff09;广度优先搜索(BFS)算法 3、二叉树的性质详解 4、二叉树的类型 &#xff08;1&#xff09;满二叉树 &…

IT服务台追踪的关键故障指标

指标是 IT 服务管理的核心&#xff0c;可提供运营见解并帮助确定持续改进的领域。通常的服务台指标有助于展示内部运营效率。为 例如&#xff0c;衡量在指定时间内解决的工单数量的 SLA 是展示服务台效率的关键因素。另一方面&#xff0c;故障指标可帮助团队识别 IT 基础架构中…

Linux基本指令学习(入门)

Linux基本指令学习 0.在xshell中登录自己的虚拟机1. ls指令2. pwd命令3. cd 指令4. touch指令5.mkdir指令6.rmdir指令 && rm 指令7.man指令&#xff1a;8.cp指令9.mv指令&#xff1a;10.cat11.more指令12.less指令13.head指令14.tail指令15.时间相关的指令16.Cal指令17…

【Linux】Tomcat 部署及优化

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 Tomcat 部署及优化 一、Tomcat 概述1.Tomcat 介绍2.Tomcat 核心组件3.Tomcat 组件结构4.Tomcat 处理请求过程 二、Tomcat 部署步骤1.关闭防火墙2.安装JDK3.设置JDK环境变量4.…

SQL基础培训16-日期处理

进度16-日期处理-SQL基础培训 知识点(学习作业就是按示例练习一遍): 1、系统当前日期 select getdate() as 当前系统日期 --建表时&

Antd时间轴Timeline遍历数据

Antd时间轴遍历数据 <Timelineitems{data.map((item) > {return { children: item };})}/>

Java实现手动操作定时任务功能的简单例子(动态创建定时任务)

还记得在前公司与同事共同开发一个在页面上统一管理定时提醒任务的功能&#xff0c;实际业务可能会复杂一些&#xff0c;它需要结合小程序或公众号平台对各个用户进行周期性&#xff08;按季度、按月、按日等&#xff09;的消息推送。由于我当时负责的是小程序和公众号平台方面…