数据结构(5)树形结构——二叉搜索树(JAVA代码实现)

news2025/7/20 5:58:00

5.1.概述

二叉搜索树,也叫二叉查找树、二叉排序树,顾名思义,这种二叉树是专门用来进行数据查找的二叉树。二叉搜索树的查找其实就是二分查找。

二叉搜索树的定义:

  • 二叉搜索树可以为空
  • 如果二叉搜索树不为空,那么每个有孩子结点的结点,其左孩子的值一定要小于它,其右孩子的值一定要大于它。

二叉搜索树的操作集:

既然是专门用来进行查找的二叉搜索树的操作集自然就是增删查,没有改,因为二叉搜索树中的元素都是排序好的,如果直接就地改动某个节点很可能破坏有序性,所以当发现插入的数据有误的时候先删除,再重新插入,一定要保证数据经过了插入流程,这样数据才会在对的位置,才能保证整棵的有序性。

boolean find(Object target);
Object findMin();
Object findMax();
void insert(Object data);
void delete(Object data);

5.2.操作

5.2.1.节点

节点实体如下:

public class Node {
    //数据域
    private int data;
    //指针域
    private Node left;
    private Node right;

    //遍历标志
    private boolean isOrder;

    {
        isOrder=false;
    }

    public Node(){

    }

    public Node(int data){
        this.data=data;
    }
    public int getData() {
        return data;
    }

    public void setData(int data) {
        this.data = data;
    }

    public Node getLeft() {
        return left;
    }

    public void setLeft(Node left) {
        this.left = left;
    }

    public Node getRight() {
        return right;
    }

    public void setRight(Node right) {
        this.right = right;
    }

    public boolean isOrder() {
        return isOrder;
    }

    public void setOrder(boolean order) {
        isOrder = order;
    }
}

5.2.2.插入

假设插入35,从根节点开始比较,

35>30,属于30的右子树,30的右孩子不为空,继续向下走,

35<41,属于41的左子树,41的左孩子不为空,继续向下走,

35>33,属于33的右子树。33的右孩子为空,35是33的右孩子。

代码示例:

//记录根节点
    private static Node root=null;
    //用于寻路的指针
    private static Node flag=null;
    public static void insert(Node node){
        if(root==null){
            System.out.println("我插入"+node.getData()+"作为根节点");
            root=node;
        }

        flag=root;

        while (node.getData()<flag.getData()){
            if(flag.getLeft()==null) {
                System.out.println("我在"+flag.getData()+"右边插入一个"+node.getData());
                flag.setLeft(node);
            }
            flag = flag.getLeft();
        }

        while(node.getData()>flag.getData()){
            if(flag.getRight()==null) {
                System.out.println("我在"+flag.getData()+"右边插入一个"+node.getData());
                flag.setRight(node);
            }
            flag = flag.getRight();
        }
    }

 5.2.3.查找

1.查找某个值是否存在

二叉搜索树的查找其实就是借助数据结构实现了二分查找,如果当前节点的值大于要查找的值,说明要查找的值只可能存在于当前节点的右子树,如果当前节点的值小于要查找的值,说明要查找的值只可能存在于当前节点的左子树。不断重复以上过程,遇见两种情况终止:

  • 当前节点是要查找的值,查找成功,说明值存在。
  • 当前的值不是要查找的值,且节点没有左右子树,是叶子节点,查找失败,说明值不存在。

代码示例:

public static boolean find(int target){
        //从根节点开始
        flag=root;
        while(true){
            //当前节点值为查找值
            if(flag.getData()==target){
                return true;
            }
            //向右子树查找
            if(target>flag.getData()){
                flag=flag.getRight();
            }
            //向左子树查找
            if(target<flag.getData()){
                flag=flag.getLeft();
            }
            //当前节点是叶节点
            if(flag==null){
                return false;
            }
        }
    }

2.查找最大值

从根节点开始一直沿着右子树的右孩子进行查找,右子树的最后一个右孩子一定是最大值。

public static int findMax(){
        flag=root;
        while(flag.getRight()!=null){
            flag=flag.getRight();
        }
        return flag.getData();
    }

3.查找最小值

从根节点开始一直沿着左子树的左孩子进行查找,左子树的最后一个左孩子一定是最小值。

public static int findMin() {
        flag = root;
        while (flag.getLeft() != null) {
            flag = flag.getLeft();
        }
        return flag.getData();
    }

5.2.4.删除

被删除的节点有三种情况:

  • 叶子节点,直接删除即可。
  • 只有一个孩子,用孩子节点接替被删除节点即可。
  • 左右孩子双全,用左子树中最大值接替被删除节点,用右子树中最小值接替被删除节点。

代码示例:

二叉搜索树由于是整体有序的,每个元素的变动都会造成一定范围内需要进行整体的重新排序,且排序过程是重复的,因此这个过程用递归实现更加简洁,用循环会很冗长,此处选用递归实现。

public static void delete(int target){
        flag=root;
        //由于删除节点会引起树的调整,为了以防万一根节点需要重新指向一下
        root=doDelete(flag,target);
    }

    private static Node doDelete(Node node,int target){
        //空树直接返回,或者是递归出口1:已经遍历完整棵树
        if(node == null) {
            return null;
        }
        //递归左子树
        if(target < node.getData()) {
            node.setLeft(doDelete(node.getLeft(), target));
        }
        //递归右子树
        if(target > node.getData()) {
            node.setRight(doDelete(node.getRight(), target));
        }
        //执行到此步,说明已经出递归,并且没有走递归出口1返回,说明找到了目标
        //情况1:被删除节点只有一个孩子节点
        //情况2:被删除节点为叶子节点
        //以上两种情况可以合并成一个逻辑处理,即指向自己的孩子节点即可
        if(node.getLeft() == null) {
            return node.getRight();
        }
        if(node.getRight() == null) {
            return node.getLeft();
        }
        //情况3:被删除节点左右孩子双全,找右子树中最小值接替被删除节点,右子树需递归此过程整体做调整
        Node minNode = findMinNode(node.getRight());
        node.setData(minNode.getData());
        node.setRight(doDelete(node.getRight(),minNode.getData()));
        return node;
    }

    private static Node findMinNode(Node node){
        while(node.getLeft() != null)
            node = node.getLeft();
        return node;
    }

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

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

相关文章

Design Compiler工具学习笔记(7)

目录 引言 背景知识 多时钟设计 DC 输出文件分析 实际操作 设计源码 综合脚本 综合网表 SDF文件 SDC文件 REPORT文件 引言 本篇继续学习 DC的基本使用。本篇主要学习 DC 综合之后的效果分析&#xff0c;多同步时钟设计以及 DC 综合完成之后的各种输出文件。 前文链…

微信小程序开发基础(03视图与逻辑)

学习目标 能够知道如何实现页面之间的导航跳转 能够知道如何实现下拉刷新效果 能够知道如何实现上拉加载更多效果 能够知道小程序中常用的生命周期函数 页面导航 1. 什么是页面导航 页面导航指的是页面之间的相互跳转。例如&#xff0c;浏览器中实现页面导航的方式有如下两…

关于环境保护html网页设计完整版,5个以环境为主题的网页设计与实现

&#x1f380; 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

《剑指 Offer 》—50. 第一个只出现一次的字符

《剑指 Offer 》—50. 第一个只出现一次的字符 一、题目内容 原题连接&#xff1a;https://leetcode.cn/problems/di-yi-ge-zhi-chu-xian-yi-ci-de-zi-fu-lcof/description/ 题目&#xff1a;在字符串 s 中找出第一个只出现一次的字符。如果没有&#xff0c;返回一个单空格。…

【专栏】核心篇06| Redis 存储高可用背后的模式

关注公众号 【离心计划】呀&#xff0c;一起逃离地球表面 Redis专栏合集 【专栏】01| Redis夜的第一章 【专栏】基础篇02| Redis 旁路缓存的价值 【专栏】基础篇03| Redis 花样的数据结构 【专栏】基础篇04| Redis 该怎么保证数据不丢失&#xff08;上&#xff09; 【专栏…

RabbitMQ------发布确认高级(消息回调、回退、备份交换机)(八)

RabbitMQ------发布确认高级&#xff08;八&#xff09; 可能由于某些意外情况&#xff0c;导致RabbitMQ重启&#xff0c;在RabbitMQ重启过程中&#xff0c;生产者投递消息失败&#xff0c;导致消息丢失。 如果才能够保证RabbitMQ的消息可靠性呢&#xff1f; 可能出现两种问题…

大数据毕设选题 - 深度学习火焰识别检测系统(python YOLO)

文章目录0 前言1 基于YOLO的火焰检测与识别2 课题背景3 卷积神经网络3.1 卷积层3.2 池化层3.3 激活函数&#xff1a;3.4 全连接层3.5 使用tensorflow中keras模块实现卷积神经网络4 YOLOV54.1 网络架构图4.2 输入端4.3 基准网络4.4 Neck网络4.5 Head输出层5 数据集准备5.1 数据标…

CSRF漏洞简介

今天继续给大家介绍渗透测试相关知识&#xff0c;本文主要内容是CSRF漏洞原理、产生与危害。 免责声明&#xff1a; 本文所介绍的内容仅做学习交流使用&#xff0c;严禁利用文中技术进行非法行为&#xff0c;否则造成一切严重后果自负&#xff01; 再次强调&#xff1a;严禁对未…

Maven——分模块开发与设计(重点)

目录 一、模块拆分 1.1 模块拆分思想 1.2 pojo模块拆分 1.3 dao模块拆分 1.4 service模块拆分 1.5 controller模块拆分 二、 聚合——模块聚合 三、继承——模块继承 一、模块拆分 1.1 模块拆分思想 左侧&#xff1a;我们从前的架构&#xff0c;一个人独立做的所有工作文件…

shell脚本的条件判断1:字符串和数字和比较

前言 写脚本时&#xff0c;为了让脚本更接近人类思考问题的方式&#xff0c;可以对各种情况进行判断。例如&#xff0c;经常需要判断某些条件是否成立&#xff0c;如果条件成立该如何处理&#xff0c;如果条件不成立又该如何处理&#xff0c;这些都可以通过Shell脚本的if语句结…

大数据_什么是数据中台?

目录 一、数据中台的定义 二、数据中台必备的是个核心能力 三、数据中台VS业务中台 四、数据中台VS数据仓库 五、数据中台VS现有信息架构 六、数据中台的业务价值与技术价值 一、数据中台的定义 数据中台是一套可持续“让企业的数据用起来”的机制&#xff0c;是一种战略…

vm的生命周期钩子

vm的生命周期钩子&#xff08;共11个&#xff09;&#xff1a; 前8个&#xff1a; 将要创建>调用beforeCreate函数 创建完毕>调用created函数 将要挂载>调用beforeMount函数 &#xff08;重要&#xff09;挂载完毕>调用mounted函数>【重要钩子】 将要更新…

用户画像洞察分类模型 - 前端页面展示

文章目录一、前端与数据智能二、 体验优化需求场景跳失预测交互偏好智能 UI三、 关键技术鲸幂 UICook&#xff08;智能UI&#xff09;DataCookPipCookPipeline四、 体验优化实践数据智能实践的一般流程数据采集数据分析 -如何对数据进行分析处理并得出结论数据应用 - 分析结论如…

【C++】string类接口的了解和使用

为什么我们要学string类呢&#xff1f;那是必须是为了方便啊&#xff01;在C语言中&#xff0c;我们创建一个字符串&#xff0c;有很多操作或者必须要注意的细节会把控不住&#xff0c;所以C中出现了string类&#xff0c;让我们应对字符串等oj题也方便快捷了许多&#xff01; 目…

linux搭建redis数据库实现远程c语言访问

文章目录 linux安装reidis数据库c语言使用hiredis库实现redis数据库的操作测试代码使用hiredis库制作一个redis数据库管理系统linux安装reidis数据库 linux安装reidis数据库 sudo apt-get install redis-server使用systemctl命令查看redis服务运行状态 sudo systemctl statu…

Visual C++ 2010开发的程序在其它电脑上运行提示“找不到MSVCR100D.dll”原因及解决

Visual C 2010开发的程序在其它电脑上运行提示“找不到MSVCR100D.dll”原因及解决 Microsoft Visual C&#xff08;简称Visual C、MSVC、VS或VC&#xff09;2010是微软公司的免费C开发工具&#xff0c;具有集成开发环境&#xff0c;可提供编辑C语言&#xff0c;C以及C/CLI等编程…

惊喜:2023前瞻版Java面试指南,不止八股文

前言&#xff1a; 2022年马上就要过去了&#xff0c;即将要到来的就是2023年的金三银四面试季&#xff0c;随着政策的放宽&#xff0c;经济的逐步复苏&#xff0c;岗位的需求也会越来越大&#xff0c;所以趁这段时间进行知识储备将会是最好的时间段&#xff0c;永远要做快人一…

卷积神经网络——李宏毅机器学习笔记

以Image Classification为例 第一个解释角度&#xff1a; 先将不同尺寸的image&#xff0c;rescale成大小一样的尺寸&#xff0c;再丢到model中。 下图中&#xff0c;我们希望Cross entropy 越小越好 在计算机视角下的图片&#xff1a; 3 channels 对应R G B三个通道 随着模…

VirtualBox安装openEuler方案一

下载&#xff1a; https://www.openeuler.org/zh/mirror/list/ 根据设备架构选择对应的版本&#xff1a;windows是x86架构 选择下面这个4.2G大小的&#xff1a; 安装&#xff1a; 安装部分建议参考另一篇文章&#xff1a;virtualbox安装openEuler-方案二 下面部分的安装…

Flink CDC 2.3 发布,持续优化性能,更多连接器支持增量快照,新增 Db2 支持

01Flink CDC 简介Flink CDC [1] 是基于数据库的日志 CDC 技术&#xff0c;实现了全增量一体化读取的数据集成框架。配合 Flink 优秀的管道能力和丰富的上下游生态&#xff0c;Flink CDC 可以高效实现海量数据的实时集成。作为新一代的实时数据集成框架&#xff0c;Flink CDC 具…