二叉搜索树及其Java实现

二叉搜索树(Binary Search Tree,简称BST)是一种特殊的二叉树数据结构,它满足以下特性:

  1. 有序性:对于树中的任意一个节点,其左子树中所有节点的值都小于该节点的值,而其右子树中所有节点的值都大于该节点的值。这意味着,对二叉搜索树进行中序遍历(先遍历左子树,再访问根节点,最后遍历右子树)会得到一个递增的有序序列。

  2. 结构特性:每个节点最多有两个子节点,通常称为左子节点和右子节点。没有父节点的节点称为根节点,而没有子节点的节点称为叶子节点。

二叉搜索树的这些性质使得它特别适合用于动态查找表的实现,支持几个关键操作:

  • 查找:从根节点开始,根据目标值与当前节点值的比较结果,决定是继续在左子树还是右子树中查找,直到找到目标值或遇到空节点为止。由于每次比较都可以排除一半的剩余节点,查找的平均时间复杂度为O(log n),其中n是树中节点的数量。

  • 插入:新节点总是作为叶子节点被添加。从根节点开始,沿着与新节点值的比较路径向下,直到遇到空的子节点位置,然后在此位置插入新节点。

  • 删除:删除操作相对复杂,需要考虑多种情况,如被删除节点是否有子节点,删除后需要保持二叉搜索树的性质。处理要删除的节点有两个子节点的情况时,可以找到右子树的最小值节点来替换待删除节点,然后将其删除;或者找到左子树的最大节点来替换待删除节点,然后将其删除。如下图中,加入待删除节点是10,则可以用9或者15来顶10,核心是保持BST的有序特性。

代码实现

package org.example.code;

/**
 * @author Mazai-Liu
 * @time 2024/6/22
 */
public class BST {

    public static void main(String[] args) {
        BST tree = new BST();
        tree.insert(50);
        tree.insert(30);
        tree.insert(20);
        tree.insert(40);
        tree.insert(70);
        tree.insert(60);
        tree.insert(80);

        System.out.println("Inorder traversal of the given tree:");
        tree.traversal();

        System.out.println("\n\nDelete 20");
        tree.delete(20);
        System.out.println("Inorder traversal after deletion:");
        tree.traversal();

        System.out.println("\n\nSearching for 20: " + (tree.search(20) != null ? "Found" : "Not Found"));
    }

    // 树节点定义
    static class TreeNode {
        public int val;
        public TreeNode left;
        public TreeNode right;

        public TreeNode(int val) {
            this.val = val;
        }
    }
    // BST的根节点
    private TreeNode root;

    // 搜索值
    public TreeNode search(int val) {
        return doSearch(root, val);
    }
    // 插入值
    public void insert(int key) {
        root = doAdd(root, key);
    }
    // 删除
    public void delete(int key) {
        // 用左子树的最大节点、右子树的最小节点来顶
        root = doDelete(root, key);
    }
    // 遍历
    public void traversal() {
        doTraversal(root);
    }

    // 根据有序的特性进行查找
    private TreeNode doSearch(TreeNode root, int val) {
        if(root == null || root.val == val)
            return root;

        return root.val > val ? doSearch(root.left, val) : doSearch(root.right, val);
    }

    private TreeNode doAdd(TreeNode root, int val) {
        if(root == null) 
            return new TreeNode(val);
        if(root.val > val)
            root.left = doAdd(root.left, val);
        else
            root.right = doAdd(root.right, val);
        return root;
    }
    
    // 中序遍历
    private void doTraversal(TreeNode root) {
        if(root == null)
            return;
        doTraversal(root.left);
        System.out.println(root.val);
        doTraversal(root.right);
    }

    // 删除节点并更新中间节点的引用情况
    private TreeNode doDelete(TreeNode root, int key) {
        if(root == null)
            return root;
        if(root.val > key)
            root.left =  doDelete(root.left, key);
        else if(root.val < key)
            root.right = doDelete(root.right, key);
        else {
            // 没左或没右可以直接用另一边来顶了
            if (root.right == null)
                return root.left;
            if (root.left == null)
                return root.right;

            // 找右子树的最小节点来顶
//            TreeNode theNode = root.right;
//            while (theNode.left != null) {
//                theNode = theNode.left;
//            }
//            root.val = theNode.val;
//            root.right = doDelete(root.right, theNode.val);

            // 找左子树的最大节点来顶
            TreeNode theNode = root.left;
            while (theNode.right != null) {
                theNode = theNode.right;
            }
            root.val = theNode.val;
            // 记得删除用来顶的那个元素
            root.left = doDelete(root.left, theNode.val);
        }
        return root;
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Web Worker 学习及使用

了解什么是 Web Worker 提供了可以在后台线程中运行 js 的方法。可以不占用主线程&#xff0c;不干扰用户界面&#xff0c;可以用来执行复杂、耗时的任务。 在worker中运行的是另一个全局上下文&#xff0c;不能直接获取 Window 全局对象。不同的 worker 可以分为专用和共享&…

FreeCAD中事务机制实现原理分析

1.基本实现思路 实现一个文件的撤销重做最简单的思想就是&#xff0c;在每个撤销重做节点处保存一份文件的内容&#xff0c;撤销重做时&#xff0c;分别替换对应节点处的文件内容即可。这种做法开销太大&#xff0c;每个节点处都需要保存一份完整的文档内容&#xff0c;每次撤…

fastapi+vue3+primeflex前后端分离开发项目第一个程序

安装axios axios是用来请求后端接口的。 https://www.axios-http.cn/docs/intro pnpm 是一个前端的包管理工具&#xff0c;当我们需要给前端项目添加新的依赖的时候&#xff0c;就可以使用pnpm install 命令进行安装。 pnpm install axios安装 primeflex primeflex是一个cs…

十大经典排序算法——插入排序与希尔排序(超详解)

一、插入排序 1.基本思想 直接插入排序是一种简单的插入排序法&#xff0c;基本思想是&#xff1a;把待排序的记录按其数值的大小逐个插入到一个已经排好序的有序序列中&#xff0c;直到所有的记录插入完为止&#xff0c;得到一个新的有序序列。 2.直接插入排序 当插入第 e…

(八)ReactHooks使用规则

ReactHooks使用规则 只能在组件中或者其他自定义Hook函数中使用只能在组件的顶层调用&#xff0c;不能嵌套在if、for、其他函数中

模拟原神圣遗物系统-小森设计项目,设计圣遗物词条基类

项目分析 首先需要理解圣遗物的方方面面 比如说圣遗物主词条部分和副词条部分都有那些特点 稍等一会&#xff1a;原神&#xff0c;启动&#xff01; 在此说明了什么&#xff1f; 这是完全体 &#xff1a;主副 词条都有 如果 升级直接暴击率 那么就留点 或者是另外的元素充能 …

如何自制一个Spring Boot Starter并推送到远端公服

在现代Java开发中&#xff0c;Spring Boot无疑是一个强大且便捷的框架&#xff0c;它通过提供大量的Starter来简化依赖管理和项目配置。有时&#xff0c;我们可能需要为特定功能或团队定制Starter。本文将指导你如何创建自己的Spring Boot Starter并将其推送到远程公共服务器上…

[SAP ABAP] 运算符与操作符

1.算数运算符 算术运算符描述加法-减法*乘法/除法MOD取余 示例1 输出结果: 输出结果: 2.比较运算符 比较运算符描述示例 等于 A B A EQ B <> 不等于 A <> B A NE B >大于 A > B A GT B <小于 A < B A LT B >大于或等于 A > B A GE B <小…

33 - 连续出现的数字(高频 SQL 50 题基础版)

33 - 连续出现的数字 -- 开窗函数lead(col,n) 统计窗口内往下第n行值 -- over(partition by xxx) 按照xxx所有行进行分组 -- over(partition by xxx order by aaa) 按照xxx分组&#xff0c;按照aaa排序select distinct num as ConsecutiveNums from(select num,# 从当前记录获…

Mac M3 Pro 安装 Zookeeper-3.4.6

1、下载安装包 官方下载地址&#xff1a;https://archive.apache.org/dist/zookeeper/ 网盘下载地址&#xff1a;https://pan.baidu.com/s/1j6iy5bZkrY-GKGItenRB2w?pwdirrx 提取码: irrx 2、解压并添加环境变量 # 将安装包移动到目标目录 mv ~/Download/zookeeper-3.4.6.…

回归预测 | Matlab实现NGO-HKELM北方苍鹰算法优化混合核极限学习机多变量回归预测

回归预测 | Matlab实现NGO-HKELM北方苍鹰算法优化混合核极限学习机多变量回归预测 目录 回归预测 | Matlab实现NGO-HKELM北方苍鹰算法优化混合核极限学习机多变量回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现NGO-HKELM北方苍鹰算法优化混合核极限…

elementui表格el-table最右侧操作列展示不完全

解决方法 .el-table__fixed,.el-table__fixed-right{height:100% !important;}

C++继承与多态—多重继承的那些坑该怎么填

课程总目录 文章目录 一、虚基类和虚继承二、菱形继承的问题 一、虚基类和虚继承 虚基类&#xff1a;被虚继承的类&#xff0c;就称为虚基类 virtual作用&#xff1a; virtual修饰成员方法是虚函数可以修饰继承方式&#xff0c;是虚继承&#xff0c;被虚继承的类就称为虚基类…

MySQL学习笔记-进阶篇-视图和存储过程

四、视图和存储过程 视图 存储过程 基本语法 创建 CREATE PROCEDURE ([参数列表]) BEGIN --SQL END; 调用 CALL 存储过程名&#xff08;[参数列表]&#xff09; 查看 --查看指定数据库的存储过程及状态信息 SELECT * FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_SHCEMA…

【网络安全的神秘世界】关于Linux中一些好玩的字符游戏

&#x1f31d;博客主页&#xff1a;泥菩萨 &#x1f496;专栏&#xff1a;Linux探索之旅 | 网络安全的神秘世界 | 专接本 | 每天学会一个渗透测试工具 佛祖保佑 把 motd 通过xtp拖到Linux中 liyangUbuntu2204:~$ cp motd /etc/motd #一定要放在etc下 liyangUbuntu2204:~$ exi…

90 Realistic Arctic Environment Textures snow(90+种逼真的北极环境纹理--雪、冰及更多)

一组90多个逼真的雪、冰、雪地岩石和其他被雪覆盖的地面纹理,供在雪地环境中使用。每个纹理都是可贴的/无缝的,并且完全兼容各种不同的场景--标准的Unity地形、Unity标准着色器、URP、HDRP等等都兼容。 所有的纹理都是4096x4096,并包括一个HDRP掩码,以完全支持HDRP。 特点。…

Web项目部署后浏览器刷新返回Nginx的404错误对应解决方案

data: 2024/6/22 16:05:34 周六 limou3434 叠甲&#xff1a;以下文章主要是依靠我的实际编码学习中总结出来的经验之谈&#xff0c;求逻辑自洽&#xff0c;不能百分百保证正确&#xff0c;有错误、未定义、不合适的内容请尽情指出&#xff01; 文章目录 1.源头2.排错3.原因4.解…

MSPM0G3507——特殊的串口0

在烧录器中有串口0&#xff0c;默认也是串口0通过烧录线给电脑发数据。 如果要改变&#xff0c;需要变一下LP上的跳线帽。 需要更改如下位置的跳线帽

fastapi+vue3+primeflex前后端分离开发项目环境搭建

创建后端项目 创建文件夹&#xff1a; mkdir backend创建python虚拟环境&#xff1a; python -m venv venv使用Pycharm打开文件夹&#xff0c;然后配置python解释器为venv虚拟环境。 安装fastapi&#xff1a; pip install "fastapi[all]"编写第一个程序&#xf…

Vue56-组件的自定义事件

一、什么是自定义事件 二、子组件—【传值】—>父组件 2-1、prop属性 2-2、自定义事件 v-on在谁身上&#xff0c;就给谁绑定事件&#xff01; 给谁绑定的事件&#xff0c;想触发就找谁&#xff01; 2-3、prop属性VS自定义属性 2-4、简写形式 2-5、ref属性实现 加了ref属性…