二叉树的构建(java基于数组)

news2024/10/7 3:32:21

前言

        二叉树在算法中是经常考察的点,但是要在本地测试的话,就必须自己构建二叉树。在算法题中,一般给我们的都是一个数组,或者是二叉树的形状。因此,需要将数组转换为二叉树,这样才能测试出自己的代码是否符合题意。

构建基础知识

我采用的是完全二叉树的方式进行构建二叉树的,因此需要知道完全二叉树的性质:

        对于完全二叉树,若从上至下,从左至右,并从1开始进行编号,规则如下:

        编号为 i 的节点                

  1. 其左孩子的编号必为 2*i
  2. 其右孩子的编号必为 2*i + 1         

构建事项

由于我采用的是数组实现,因此与基本的性质有一些差别,这是因为数组的下标是从0开始计算的,从而规则更改为:

        编号为  i  的节点

  1. 其左孩子的编号必为 2 * i + 1
  2. 其右孩子的编号必为 2 * i + 2 

正式构建

构建一般的(int)二叉树

说明:

        因为一般的算法题中是以int 数组为代表的考题,因此将其单独提出来

构建二叉树节点

代码实现

public class TreeNode {
    // 节点数据
    public int val;
    // 左节点 遍历
    public TreeNode left;
    // 右节点
    public TreeNode right;
    public TreeNode() {
    }
    public TreeNode(int val) {
        this.val = val;
    }
}

二叉树构建方法

代码实现

   public TreeNode intArrayToBTree(int [] arrs) {
        // 判空处理,返回空节点
        if (arrs == null || arrs.length == 0) {
            return new TreeNode();
        }
        // 创建和数组长度相同的集合
        List<TreeNode> nodes = new ArrayList<>(arrs.length);
        // 遍历数组,将数组元素转为集合节点
        for (int obj : arrs) {
            TreeNode treeNode = new TreeNode();
            treeNode.val = obj;
            nodes.add(treeNode);
        }
        //  按照完全二叉树的规则构建,数组中的后半部分元素都是叶子节点,它们没有左右子节点。所以循环只需要处理前半部分的非叶子节点即可。
        //  i < arrs.length/2 - 1  能够将所有左右子节点不为null的元素给遍历出来,剩下最后一个(在左节点上)或者最后两个(在右节点上)
        //  保证循环只在前半部分有效的节点范围内进行迭代,避免处理不必要的叶子节点。
        for (int i = 0; i < arrs.length/2 - 1; i++) {
            TreeNode node = nodes.get(i);
            // 首先,由于是通过数组构建的二叉树(数组下标从0开始)
            // 其次,由完全二叉树的性质(从1开始计数,左孩子为2i,右孩子为2i  +1 )  再结合 数组下标0 开始计数 可知:
            // 树的左节点为 2i +1;树的右节点为:2i +2
            node.left = nodes.get(i*2 + 1);
            node.right = nodes.get(i*2 + 2);
        }
        // 只有当总节点数是奇数时,最后一个父节点才有右子节点
        int lastPNodeIndex = arrs.length/2 - 1;
        TreeNode lastPNode = nodes.get(lastPNodeIndex);
        // 左孩子节点
        lastPNode.left = nodes.get(lastPNodeIndex*2 + 1);
        if (arrs.length%2 != 0) {
            lastPNode.right = nodes.get(lastPNodeIndex*2 + 2);
        }

        return nodes.get(0);
    }

测试方法

代码实现 


    public static void main(String[] args) {
        int [] arr = {1,3,2,5,3,9};
        TreeNode treeNode = new TreeNode();
        TreeNode root = treeNode.intArrayToBTree(arr);
    }

测试过程

使用Debug模式运行(主要看fori循环那里)

在经过第一次的循环(将数组元素转为节点元素的循环)

        由于QQ长截图失效,将其截图为两张图,其实最主要的是观察第一个节点的变化,之后就直接第一个节点变化的值。 

        在第二个for循环开始前,需要关注一下循环判断条件

         i < arrs.length/2 - 1

         i < arrs.length/2 - 1 能够将所有左右子节点都不为null的元素给遍历出来,直至叶子节点,剩下最后一个叶子节点(在左节点上)或者最后两个叶子节点(在右节点上)

        这个条件是为了保证循环只在前半部分有效的节点范围内进行迭代,避免处理不必要的叶子节点。

 进入第一次for循环(i = 0)

 经过第一次循环(i = 0),可知根节点为1,其左节点为3(其下还没遍历出左右孩子),其右节点为2(其下还没遍历出左右孩子)

 进入第二次for循环(i = 1)

第 二次循环确定了根节点1的左孩子 的 左右孩子的值(也就是在第一次遍历基础上,得到遍历左节点3的左右孩子的值),从结果中可知,根节点的右孩子在这一次循环中没有添加进来,因为默认一次只添加左右孩子两个值,而节点9 是最后一个值,没有满足循环条件,因此右节点没有变化。

        当i = 1 结束时,会进行 i++ 操作,操作完成后 i = 2,不满足循环条件, 循环对于最后一个节点9,需要对其进行判断

        int lastPNodeIndex = arrs.length/2 - 1;
        TreeNode lastPNode = nodes.get(lastPNodeIndex);
        // 左孩子节点
        lastPNode.left = nodes.get(lastPNodeIndex*2 + 1);
        // 只有当总节点数是奇数时,最后一个父节点才有右子节点
        if (arrs.length%2 != 0) {
            lastPNode.right = nodes.get(lastPNodeIndex*2 + 2);
        }

测试结果:

根节点:       1        

第一层节点:3        2

第二层节点:5        3        9

构成的完全二叉树:

                         1

                       /    \

                     3      2

                   /    \    /  \

                  5    3  9   (null)

构建特殊的(Object) 二叉树

        有些算法场景也会用到其他类型作为数据域的节点构成的二叉树,因此也在上面基础上将int类的的数据节点改为Object类型的数据节点,其实现方法大同小异。

构建二叉树节点

public class TreeNode {
    // 节点数据
    public Object data;
    // 左节点 遍历
    public TreeNode left;
    // 右节点
    public TreeNode right;

    public TreeNode() {
    }

    public TreeNode(Object data) {
        this.data = data;
    }
    public TreeNode(Object data, TreeNode left, TreeNode right) {
        this.data = data;
        this.left = left;
        this.right = right;
    }
}

 二叉树构建方法

   /**
     * 数组遍历构成二叉树
     * @param arrs 数组
     * @return 二叉树根节点
     */
    public TreeNode arrayToBTree(Object[] arrs) {
        if (arrs == null || arrs.length == 0) {
            return new TreeNode();
        }

        List<TreeNode> nodes = new ArrayList<>(arrs.length);
        for (Object obj : arrs) {
            TreeNode treeNode = new TreeNode();
            treeNode.data = obj;
            nodes.add(treeNode);
        }

        for (int i = 0; i < arrs.length/2 - 1; i++) {
            TreeNode node = nodes.get(i);
            node.left = nodes.get(i*2 + 1);
            node.right = nodes.get(i*2 + 2);
        }
        // 只有当总节点数是奇数时,最后一个父节点才有右子节点
        int lastPNodeIndex = arrs.length/2 - 1;
        TreeNode lastPNode = nodes.get(lastPNodeIndex);
        lastPNode.left = nodes.get(lastPNodeIndex*2 + 1);
        if (arrs.length%2 != 0) {
            lastPNode.right = nodes.get(lastPNodeIndex*2 + 2);
        }

        return nodes.get(0);
    }

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

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

相关文章

Linux文本处理工具和正则表达式

Linux文本处理工具和正则表达式 一.查看、截取和修改文本的工具 1.查看文本的工具 cat 最常用的文件查看命令&#xff1b;当不指明文件或者文件名为一杠’-时&#xff0c;读取标准输入。 cat [OPTION]... [FILE]... -A&#xff1a;显示所有控制符(tab键:^I;行结束符:$) -…

安科瑞故障电弧在体育场馆的应用-安科瑞黄安南

应用场景 一般应用于末端照明回路 功能 1.支持1路剩余电流&#xff0c;外接漏电互感器 2.支持4路温度&#xff0c;外接温度传感器 3.支持32路故障电弧&#xff0c;外接故障电弧传感器 4.支持2DI&#xff0c;2DO 5.声光报警&#xff0c;LCD点阵液晶显示 6.导轨式安装&…

基于ChatYuan-large-v2 语言模型 Fine-tuning 微调训练 广告生成 任务

一、ChatYuan-large-v2 ChatYuan-large-v2是一个开源的支持中英双语的功能型对话语言大模型&#xff0c;与其他 LLM 不同的是模型十分轻量化&#xff0c;并且在轻量化的同时效果相对还不错&#xff0c;仅仅通过0.7B参数量就可以实现10B模型的基础效果&#xff0c;正是其如此的…

基于YOLOv7开发构建MSTAR雷达影像目标检测系统

MSTAR&#xff08;Moving and Stationary Target Acquisition and Recognition&#xff09;数据集是一个基于合成孔径雷达&#xff08;Synthetic Aperture Radar&#xff0c;SAR&#xff09;图像的目标检测和识别数据集。它是针对目标检测、机器学习和模式识别算法的研究和评估…

Visual Studio 2019 详细安装教程(图文版)

前言 Visual Studio 2019 安装包的下载教程、安装教程 教程 博主博客链接&#xff1a;https://blog.csdn.net/m0_74014525 关注博主&#xff0c;后期持续更新系列文章 ********文章附有百度网盘安装包链接********* 系列文章 第一篇&#xff1a;Visual Studio 2019 详细安装教…

MobiSys 2023 | 多用户心跳监测的双重成形声学感知

注1:本文系“无线感知论文速递”系列之一,致力于简洁清晰完整地介绍、解读无线感知领域最新的顶会/顶刊论文(包括但不限于 Nature/Science及其子刊; MobiCom, Sigcom, MobiSys, NSDI, SenSys, Ubicomp; JSAC, 雷达学报 等)。本次介绍的论文是:<<MobiSys’23,Multi-User A…

特殊符号的制作 台风 示例 使用第三方工具 Photoshop 地理信息系统空间分析实验教程 第三版

特殊符号的制作 首先这是一个含有字符的&#xff0c;使用arcgis自带的符号编辑器制作比较困难。所以我们准备采用Adobe Photoshop 来进行制作符号&#xff0c;然后直接导入符号的图片文件作为符号 我们打开ps&#xff0c;根据上面的图片的像素长宽比&#xff0c;设定合适的高度…

高中生python零基础怎么学,python高中生自学行吗

这篇文章主要介绍了高中学历学python好找工作吗&#xff0c;具有一定借鉴价值&#xff0c;需要的朋友可以参考下。希望大家阅读完这篇文章后大有收获&#xff0c;下面让小编带着大家一起了解一下。 学习python的第九天 根据我们前面这几天的学习&#xff0c;我们掌握了Python的…

nginx环境部署

目录 一、yum安装 二、源码安装 三、测试结果 一、yum安装 1、先查找本地yum源上有没有nginx包 yum list | grep nginx 2、rpm安装 rpm -Uvh http://nginx.org/packages/centos/7/x86_64/RPMS/nginx-1.14.2-1.el7_4.ngx.x86_64.rpm 3、查看安装是否成功 rpm -pa | grep…

Pytorch迁移学习使用MobileNet v3网络模型进行猫狗预测二分类

目录 1. MobileNet 1.1 MobileNet v1 1.1.1 深度可分离卷积 1.1.2 宽度和分辨率调整 1.2 MobileNet v2 1.2.1 倒残差模块 1.3 MobileNet v3 1.3.1 MobieNet V3 Block 1.3.2 MobileNet V3-Large网络结构 1.3.3 MobileNet V3预测猫狗二分类问题 送书活动 1. MobileNet …

【力扣每日一题】2023.8.6 两两交换链表中的节点

目录 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 代码&#xff1a; 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 题目给我们一个链表&#xff0c;让我们两两交换相邻节点的值&#xff0c;并且不能通过修改节点内部的值来达到这一目的&#xff0c;如果可…

NERFS 与现实捕捉 - 弥合现实世界与数字世界之间的差距

NERF介绍 近年来&#xff0c;计算机视觉和图形领域取得了显着的进步&#xff0c;催生了革命性的技术&#xff0c;改变了各个行业。 NERFS&#xff08;神经辐射场&#xff09;和现实捕捉是两项备受关注的重要技术。 NERFS 和现实捕捉都是以数字形式捕捉和重建现实世界的强大工具…

无涯教程-Perl - dbmclose函数

描述 此函数关闭哈希和DBM文件之间的绑定。将领带功能与合适的模块配合使用。 语法 以下是此函数的简单语法- dbmclose HASH返回值 如果失败,此函数返回0,如果成功,则返回1。 请注意,在大型DBM文件上使用键和值之类的功能时,它们可能会返回巨大的列表。您可能更喜欢使用e…

HBase-写流程

写流程顺序正如API编写顺序&#xff0c;首先创建HBase的重量级连接 &#xff08;1&#xff09;读取本地缓存中的Meta表信息&#xff1b;&#xff08;第一次启动客户端为空&#xff09; &#xff08;2&#xff09;向ZK发起读取Meta表所在位置的请求&#xff1b; &#xff08;…

chapter13:springboot与任务

Spring Boot与任务视频 1. 异步任务 使用注解 Async 开启一个异步线程任务&#xff0c; 需要在主启动类上添加注解EnableAsync开启异步配置&#xff1b; Service public class AsyncService {Asyncpublic void hello() {try {Thread.sleep(3000);} catch (InterruptedExcept…

为什么很多人都在吹ChatGPT改变世界?一文全面了解

ChatGPT早已让全世界的互联网炸锅&#xff0c;它已经从一个新颖的聊天机器人演变成一项推动下一个创新时代到来的技术。已经很久没有出现一款让大家充满兴趣、兴奋、恐惧且具有争议的科技产品了。 如果你现在才接触到它&#xff0c;你可能会想知道这到底是怎么回事。这里建议你…

linux gcc __attribute__

__attribute__ 1. 函数属性1.1 __attribute__((noreturn))1.2 __attribute__((format))1.3 __attribute__((const)) 2. 变量属性2.1. __attribute__((aligned))2.2. __attribute__((packed)) 3. 类型属性 __attribute__ 是 GCC 编译器提供的一种特殊语法&#xff0c;它可以用于…

测试该知道的二三事:浅谈响应式网页设计

1.起因 最近几天正巧在帮朋友的公司团队做质量保障体系的培训&#xff0c;在此期间与几个测试人员闲聊&#xff0c;正是其中的一件事让我对今天的话题提起了兴趣&#xff1a;朋友公司里的研发团队招了一个应届毕业生&#xff0c;做了半年之后接了某个web项目的其中一个拓展功能…

质检工具(FindBugs、CheckStyle、Junit、Jmeter、Apifox)

1、Findbugs IDEA软件中可以装该插件,2018版本以前主要搜索FindBugs-IDEA 、2018版本以后主要搜索 SpotBugs。 1.1、FindBugs-IDEA安装及使用流程: 1.2、SpotBugs安装及使用流程: 2、Checkstyle IDEA软件中可以装该插件,所有版本的插件一致:CheckStyle 2.1、安装流程…

【C# 基础精讲】为什么选择C# ?

C#&#xff08;C Sharp&#xff09;是由微软开发的一种通用、面向对象的编程语言。它最初于2000年发布&#xff0c;自那时以来逐渐成为开发者的首选之一。C#的设计目标是提供一种简单、现代、可靠且安全的编程语言&#xff0c;使开发者能够轻松构建各种类型的应用程序。 为什么…