Java开发 - 树(二叉树,二叉排序树,红黑树)(二)

简介: Java开发 - 树(二叉树,二叉排序树,红黑树)

增加元素


判断root是否为null
  -为null,则将元素封装成节点,称为root,返回true
  -不为null,和root进行比较,比较的目的是将元素尝试添加为root的left/right子树
    - 和root相等,添加失败,返回false,结束
    - 大于>root,尝试添加为root的right;判断right是否为null,
      - 为null,则让新元素封装成节点,称为right,添加成功,返回true
      - 不为null,继续和right的节点进行比较,尝试将元素添加为right的left/right子树
    - 小于,同理

增加元素需要先判断root是否为null


为null,将元素封装成根结点,返回true;

非null,和root进行比较,这是为了判断新元素是添加左子树还是右子树,但不一定添加成功

和root相等,那么添加失败,返回false,结束

大于root,尝试添加为root的右子树,判断right是否为null;

为null,将新元素封装成节点,成为右子树right,添加完成,返回true;

不为null,和right节点进行比较,尝试将该元素添加为right的left/right子树(这里递归就出现了)

小于root,尝试添加为root的左子树,判断left是否为null;

为null,将新元素封装成节点,成为左子树left,添加完成,返回true;

不为null,和left节点进行比较,尝试将该元素添加为left的left/right子树(这里递归就出现了)


思路理清了,那我们就开始写代码:

//添加元素
    public boolean add(E e){
        //判断root是否为null,为null,成为根节点
        if (root==null) {
            root = new Node(e);
            return true;
        }
        //root不为null,添加
        return root.append(e);
    }

Node内的添加方法:

       //向某个节点上添加给定的元素,尝试让新元素称为其左/右子树
        public boolean append(E e) {
            if (e.compareTo(ele) == 0) {
                return false;
            } else if (e.compareTo(ele) < 0) {
                if (left == null) {
                    left = new Node(e);
                    return true;
                }
                return left.append(e);
            } else {
                if (right == null) {
                    right = new Node(e);
                    return true;
                }
                return right.append(e);
            }
        }


查询元素


查询元素也需要先判断root是否为null


为null,树中没有节点,返回null;

非null,判断root节点是否为需要查找的元素

相等,root节点就是需要的元素,返回root节点,结束;

大于ele,就到节点的right去查找相等节点,判断right节点是否存在

为null,说明查询的元素不在此树中,返回null

非null,判断right节点是不是要找的节点,往后一直重复上述操作,直到找到或找不到为止

小于ele,就到节点的left去查找相等节点,判断left节点是否存在

为null,说明查询的元素不在此树中,返回null

非null,判断left节点是不是要找的节点,往后一直重复上述操作,直到找到或找不到为止


用代码来写下这个过程:

    //根据元素查询对应的节点对象
    public Node get(E e){
        //判断root是否为null
        if (root==null)
            return null;
        //root不为空,则判断root是否为目标节点
        return root.isDestNode(e);
    }

Node内的查询:

        //用于判断调用方法的节点是否为目标节点
        public Node isDestNode(E e) {
            //判断e是否和当前节点的元素相等,若相等,说明为目标节点,返回当前节点即可
            if (e.compareTo(ele)==0)
                return this;
            else if (e.compareTo(ele)>0){  //e大于当前节点,到right上继续查找
                //若right为null,说明目标元素不存在树中,返回null
                if (right==null)
                    return null;
                return right.isDestNode(e);
            }else {  //e小于当前节点,到left上继续查找
                if (left==null)
                    return null;
                return left.isDestNode(e);
            }
        }


修改元素


修改其实很简单,首先是查找,查找到之后,直接将新的元素指向那个节点。


我们可以定义这个方法如下:

set(E ele, E newEle)

修改理论上是可行的,但是在修改的时候,会不会引起重新排序呢?这对整个树结构是有影响的,代码似乎也没有刚开始说的那么简单了,重新排序对性能也有影响,所以二叉树可不提供修改方法。


删除元素


这要看删的是谁,如果删除的是叶子结点,那直接删了就好,不需要做什么判断,也不存在排序问题。一旦删除的是中间的节点,看下图:

1.png

假如删的是2或者6,这时候就要考虑谁上去的问题了。


所以删除分为三种情况:


删除叶子结点:将其父节点指向它的引用置为null;

删除有一棵子树的节点:将其父节点的指向变更为被删除的节点的子节点;

删除有两颗子树的节点:让被删除节点的前驱节点或者后继节点上来替换此节点;

前驱节点和后继节点是指升序排列后,删除节点的前一个元素叫做前驱节点,删除节点的后一个元素叫做后继节点

代码写起来会非常复杂,体验很差,所以就不写了,理解了就行,有兴趣的同学可自行尝试。


遍历二叉树


遍历的方式分为三种:

先序遍历:根  左  右

中序遍历:左  根  右

后序遍历:左  右  根


什么意思呢?我们根据一棵树来说:

1.png

先序遍历:4,2,1,3,6,5,7(即先根,后左,再右)

中序遍历:1,2,3,4,5,6,7(即先左,后根,再右,也叫升序排列)

后序遍历:1,3,2,5,7,6 ,4(即先左,后右,再根)


重写toString


目的是为了实现输出引用,将二叉树中的元素遍历,并以此格式输出:[1,2,3,4,5,6,7]输出,没有节点,返回[]。

    //重写toString
    @Override
    public String toString() {
        //判断root是否为null,为null,返回"[]"
        if (root==null)
            return "[]";
        //进行中序遍历
        StringBuilder builder = new StringBuilder("[");
        return root.middleOrder(builder).replace(builder.length()-1,builder.length(),"]").toString();

Node内的方法:

        public StringBuilder middleOrder(StringBuilder builder) {
            //左
            if (left!=null){
                left.middleOrder(builder);
            }
            //取根的值
            builder.append(ele).append(",");
            //取右
            if (right!=null){
                right.middleOrder(builder);
            }
            //以上三步操作结束,得到遍历树后的元素拼接结果,将最后的逗号替换为]
            return builder;
        }

中序遍历这里有个递归,我们要明白的是,最终所有的代码都要取到根的值,这个节点是相对的,每个节点都会是这个根,这样才能拼接出字符串。大家可以动手尝试下其他遍历方式的写法,这里不再赘述。


二叉排序树的极端情况

1.png

这就是失衡二叉树,失衡二叉树是不希望存在的,因为它失去了二叉树本身的优势特点,这种状态和单向链表一样,单向链表的效率如何,想必大家都是知道的。


所以在设计数据结构的时候,已经考虑了这种情况,出现了两种新的数据结构,他们都基于二叉排序树,保留了其优势,又避免了这个缺点。


他们是平衡二叉树和红黑树。

目录
相关文章
|
1月前
|
Java API Maven
如何使用Java开发抖音API接口?
在数字化时代,社交媒体平台如抖音成为生活的重要部分。本文详细介绍了如何用Java开发抖音API接口,从创建开发者账号、申请API权限、准备开发环境,到编写代码、测试运行及注意事项,全面覆盖了整个开发流程。
109 10
|
29天前
|
监控 Java API
如何使用Java语言快速开发一套智慧工地系统
使用Java开发智慧工地系统,采用Spring Cloud微服务架构和前后端分离设计,结合MySQL、MongoDB数据库及RESTful API,集成人脸识别、视频监控、设备与环境监测等功能模块,运用Spark/Flink处理大数据,ECharts/AntV G2实现数据可视化,确保系统安全与性能,采用敏捷开发模式,提供详尽文档与用户培训,支持云部署与容器化管理,快速构建高效、灵活的智慧工地解决方案。
|
19天前
|
Java 开发者 微服务
Spring Boot 入门:简化 Java Web 开发的强大工具
Spring Boot 是一个开源的 Java 基础框架,用于创建独立、生产级别的基于Spring框架的应用程序。它旨在简化Spring应用的初始搭建以及开发过程。
38 6
Spring Boot 入门:简化 Java Web 开发的强大工具
|
6天前
|
存储 JavaScript 前端开发
基于 SpringBoot 和 Vue 开发校园点餐订餐外卖跑腿Java源码
一个非常实用的校园外卖系统,基于 SpringBoot 和 Vue 的开发。这一系统源于黑马的外卖案例项目 经过站长的进一步改进和优化,提供了更丰富的功能和更高的可用性。 这个项目的架构设计非常有趣。虽然它采用了SpringBoot和Vue的组合,但并不是一个完全分离的项目。 前端视图通过JS的方式引入了Vue和Element UI,既能利用Vue的快速开发优势,
52 13
|
11天前
|
算法 Java API
如何使用Java开发获得淘宝商品描述API接口?
本文详细介绍如何使用Java开发调用淘宝商品描述API接口,涵盖从注册淘宝开放平台账号、阅读平台规则、创建应用并申请接口权限,到安装开发工具、配置开发环境、获取访问令牌,以及具体的Java代码实现和注意事项。通过遵循这些步骤,开发者可以高效地获取商品详情、描述及图片等信息,为项目和业务增添价值。
44 10
|
5天前
|
前端开发 Java 测试技术
java日常开发中如何写出优雅的好维护的代码
代码可读性太差,实际是给团队后续开发中埋坑,优化在平时,没有那个团队会说我专门给你一个月来优化之前的代码,所以在日常开发中就要多注意可读性问题,不要写出几天之后自己都看不懂的代码。
41 2
|
14天前
|
JavaScript 安全 Java
java版药品不良反应智能监测系统源码,采用SpringBoot、Vue、MySQL技术开发
基于B/S架构,采用Java、SpringBoot、Vue、MySQL等技术自主研发的ADR智能监测系统,适用于三甲医院,支持二次开发。该系统能自动监测全院患者药物不良反应,通过移动端和PC端实时反馈,提升用药安全。系统涵盖规则管理、监测报告、系统管理三大模块,确保精准、高效地处理ADR事件。
|
1月前
|
开发框架 Java 关系型数据库
Java哪个框架适合开发API接口?
在快速发展的软件开发领域,API接口连接了不同的系统和服务。Java作为成熟的编程语言,其生态系统中出现了许多API开发框架。Magic-API因其独特优势和强大功能,成为Java开发者优选的API开发框架。本文将从核心优势、实际应用价值及未来展望等方面,深入探讨Magic-API为何值得选择。
42 2
|
1月前
|
监控 前端开发 Java
【技术开发】接口管理平台要用什么技术栈?推荐:Java+Vue3+Docker+MySQL
该文档介绍了基于Java后端和Vue3前端构建的管理系统的技术栈及功能模块,涵盖管理后台的访问、登录、首页概览、API接口管理、接口权限设置、接口监控、计费管理、账号管理、应用管理、数据库配置、站点配置及管理员个人设置等内容,并提供了访问地址及操作指南。
|
1月前
|
IDE Java 编译器
开发 Java 程序一定要安装 JDK 吗
开发Java程序通常需要安装JDK(Java Development Kit),因为它包含了编译、运行和调试Java程序所需的各种工具和环境。不过,某些集成开发环境(IDE)可能内置了JDK,或可使用在线Java编辑器,无需单独安装。
64 1
下一篇
DataWorks