JavaSE 搜索树

目录

  • 1 概念
  • 2 操作
    • 2.1 查找
    • 2.2 插入
    • 2.3 删除
  • 3 性能分析
  • 4 和 java 类集的关系

1 概念

二叉搜索树 又称 二叉排序树,它是一棵空树,或者是具有以下性质的二叉树:

  1. 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值;
  2. 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值。
  3. 它的左右子树也分别为二叉搜索树

你会发现它中序遍历的结果就是有序的。
如下图所示就是一颗二叉搜索树:
在这里插入图片描述

2 操作

2.1 查找

在这里插入图片描述
具体实现代码示例如下所示:

package bstree;class BinarySearchTree{static class BSNode{public int val;public BSNode left;public BSNode right;public BSNode(int val) {this.val = val;}}public BSNode root = null;public BSNode search(int val){if(root == null) return null;BSNode cur = root;while (cur != null){if(cur.val == val){return cur;}else if(cur.val > val){cur = cur.left;}else{cur = cur.right;}}return null;}}public class TestDemo {public static void main(String[] args) {}
}

2.2 插入

  1. 如果树为空树,即根 == null,直接插入。
    在这里插入图片描述
  2. 如果树不是空树,按照查找逻辑确定插入位置,插入新结点。
    在这里插入图片描述
    具体实现代码示例如下所示:
package bstree;class BinarySearchTree{static class BSNode{public int val;public BSNode left;public BSNode right;public BSNode(int val) {this.val = val;}}public BSNode root = null;public BSNode search(int val){if(root == null) return null;BSNode cur = root;while (cur != null){if(cur.val == val){return cur;}else if(cur.val > val){cur = cur.left;}else{cur = cur.right;}}return null;}public boolean insert(int val){BSNode bsNode = new BSNode(val);if(root == null){root = bsNode;return true;}BSNode cur = root;BSNode parent = null;while(cur != null){if(cur.val == val){return false;}else if(cur.val > val){parent = cur;cur = cur.left;}else{parent = cur;cur = cur.right;}}if(parent.val < val){parent.right = bsNode;}else{parent.left = bsNode;}return true;}}public class TestDemo {public static void preOrder(BinarySearchTree.BSNode root){if(root == null){return;}System.out.print(root.val+" ");preOrder(root.left);preOrder(root.right);}public static void inOrder(BinarySearchTree.BSNode root){if(root == null){return;}inOrder(root.left);System.out.print(root.val+" ");inOrder(root.right);}public static void main(String[] args) {BinarySearchTree binarySearchTree = new BinarySearchTree();binarySearchTree.insert(4);binarySearchTree.insert(3);binarySearchTree.insert(1);binarySearchTree.insert(15);binarySearchTree.insert(11);preOrder(binarySearchTree.root);System.out.println();inOrder(binarySearchTree.root);System.out.println();try {BinarySearchTree.BSNode ret = binarySearchTree.search(4);System.out.println(ret.val);}catch (NullPointerException e){System.out.println("没有找到当前的节点..........");e.printStackTrace();}}
}

2.3 删除

前提是删除这个节点之后,整棵树还是一棵二叉搜索树。
删除思路:
设待删除结点为 cur, 待删除结点的双亲结点为 parent。
则分为下面三种情况:

  1. cur.left == null

cur 是 root,则 root = cur.right
cur 不是 root,cur 是 parent.left,则 parent.left = cur.right
cur 不是 root,cur 是 parent.right,则 parent.right = cur.right

  1. cur.right == null

cur 是 root,则 root = cur.left
cur 不是 root,cur 是 parent.left,则 parent.left = cur.left
cur 不是 root,cur 是 parent.right,则 parent.right = cur.left

  1. cur.left != null && cur.right != null
  1. 如果像原来那样删除,那么一个节点就会出现两个父亲节点?
    需要使用替换法进行删除,即在它的右子树中寻找中序下的第一个结点(关键值最小),用它的值填补到被删除节点中,再来处理该结点的删除问题。
  2. 我们怎么知道放谁上去?
    当前需要删除的节点的左边找最大的,右边找最小的。

具体实现代码示例如下所示:

package bstree;class BinarySearchTree {static class BSNode {public int val;public BSNode left;public BSNode right;public BSNode(int val) {this.val = val;}}public BSNode root = null;public BSNode search(int val) {if (root == null) return null;BSNode cur = root;while (cur != null) {if (cur.val == val) {return cur;} else if (cur.val > val) {cur = cur.left;} else {cur = cur.right;}}return null;}public boolean insert(int val) {BSNode bsNode = new BSNode(val);if (root == null) {root = bsNode;return true;}BSNode cur = root;BSNode parent = null;while (cur != null) {if (cur.val == val) {return false;} else if (cur.val > val) {parent = cur;cur = cur.left;} else {parent = cur;cur = cur.right;}}if (parent.val < val) {parent.right = bsNode;} else {parent.left = bsNode;}return true;}public void remove(int val) {if (root == null) return;BSNode cur = root;BSNode parent = null;while(cur !=null){if (cur.val == val) {removeNode(parent,cur,val);} else if (cur.val < val) {parent = cur;cur = cur.right;} else {parent = cur;cur = cur.left;}}}public void removeNode(BSNode parent,BSNode cur,int val){if(cur.left == null){if(cur == root){root = cur.right;}else if(parent.left == cur){parent.left = cur.right;}else if(parent.right == cur){parent.right = cur.right;}}else if(cur.right == null){if(cur == root){root = cur.left;}else if(parent.left == cur){parent.left = cur.left;}else if(parent.right == cur){parent.right = cur.left;}}else{//这里采取的是右边找最小的方法BSNode targetParent = cur;BSNode target = cur.right;while(target.left != null){targetParent = target;target = target.left;}//target指向的节点就是 右边的最小值cur.val = target.val;if(target == targetParent.left){targetParent.left = target.right;}else{targetParent.right = target.right;}}}}public class TestDemo {public static void preOrder(BinarySearchTree.BSNode root){if(root == null){return;}System.out.print(root.val+" ");preOrder(root.left);preOrder(root.right);}public static void inOrder(BinarySearchTree.BSNode root){if(root == null){return;}inOrder(root.left);System.out.print(root.val+" ");inOrder(root.right);}public static void main(String[] args) {BinarySearchTree binarySearchTree = new BinarySearchTree();binarySearchTree.insert(4);binarySearchTree.insert(3);binarySearchTree.insert(1);binarySearchTree.insert(15);binarySearchTree.insert(11);preOrder(binarySearchTree.root);System.out.println();inOrder(binarySearchTree.root);System.out.println();binarySearchTree.remove(15);System.out.println("=============删除===============");preOrder(binarySearchTree.root);System.out.println();inOrder(binarySearchTree.root);System.out.println();try {BinarySearchTree.BSNode ret = binarySearchTree.search(4);System.out.println(ret.val);}catch (NullPointerException e){System.out.println("没有找到当前的节点..........");e.printStackTrace();}}
}

3 性能分析

插入和删除操作都必须先查找,查找效率代表了二叉搜索树中各个操作的性能。
对有n个结点的二叉搜索树,若每个元素查找的概率相等,则二叉搜索树平均查找长度是结点在二叉搜索树的深度的函数,即结点越深,则比较次数越多。
但对于同一个关键码集合,如果各关键码插入的次序不同,可能得到不同结构的二叉搜索树:
在这里插入图片描述
最优情况下: 二叉搜索树为完全二叉树,其比较次数为:O(log2^n)
最差情况下: 二叉搜索树退化为单支树,其比较次数为:O(n)。
问题:如果退化成单支树,二叉搜索树的性能就失去了。那能否进行改进,不论按照什么次序插入关键码,都可以是二叉搜索树的性能最佳?

4 和 java 类集的关系

TreeMap 和 TreeSet 即 java 中利用搜索树实现的 Map 和 Set;实际上用的是红黑树,而红黑树是一棵近似平衡的二叉搜索树,即在二叉搜索树的基础之上 + 颜色以及红黑树性质验证,关于红黑树的内容在后边笔记中再进行描述。

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

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

相关文章

Logistic Regression逻辑线性回归(基于diabetes数据集)

目录 介绍&#xff1a; 1、Confusion Matrix&#xff1a; 2、ROC&#xff08;Receiver Operating Characteristic&#xff09; 一、数据处理 二、建模 三、 confusion_matrix 四、 ROC&#xff08;Receiver Operating Characteristic&#xff09; 介绍&#xff1a; L…

class085 数位dp-下【算法】

class085 数位dp-下【算法】 code1 P2657 [SCOI2009] windy 数 // windy数 // 不含前导零且相邻两个数字之差至少为2的正整数被称为windy数 // windy想知道[a,b]范围上总共有多少个windy数 // 测试链接 : https://www.luogu.com.cn/problem/P2657 // 请同学们务必参考如下代码…

7款创意性前端源码特效资源分享(附在线预览效果)

分享7款非常不错炫酷的前端特效源码 其中包含css动画特效、js原生特效、svg特效等 下面我会给出特效样式图或演示效果图 但你也可以点击在线预览查看源码的最终展示效果及下载源码资源 CSS绘制iPhone 14带动态岛 纯CSS绘制iPhone 14带动态岛模型 运行初始化时还附带出场动画 …

微信小程序动态导航栏(uniapp + vant)

本文使用到vant的van-tabbar组件来实现 一、uniapp整合vant ui vant小程序版本:https://vant-contrib.gitee.io/vant-weapp/#/home 注:vant并没有uniapp的版本,所以此处是引入小程序版本的ui 1. 下载vant编译后代码 https://github.com/youzan/vant-weapp/tree/dev/dist 2…

CentOs7.x安装部署SeaTunnelWeb遇到的坑

CentOs7.x安装部署SeaTunnelWeb遇到的坑 文章目录 1. 环境2. SeaTunnel安装部署2.1下载安装包2.2 设置环境变量2.3 安装连接器插件2.4 拷贝jar包到lib下2.5 启动命令2.6 执行官方client提交任务demo 3. SeaTunnel-Web安装部署3.1 下载安装包3.2 初始化数据库脚本或修改配置appl…

element plus 表格el-table行多选单选

1 行多选-点击checkbox 添加一个 el-table-column&#xff0c;设 type 属性为 selection 即可 <template><div class"box"><el-table :data"tableData" selection-change"handleSelectionChange"><el-table-column type&…

【单调栈】LeetCode:1944队列中可以看到的人数

作者推荐 【贪心算法】【中位贪心】.执行操作使频率分数最大 题目 有 n 个人排成一个队列&#xff0c;从左到右 编号为 0 到 n - 1 。给你以一个整数数组 heights &#xff0c;每个整数 互不相同&#xff0c;heights[i] 表示第 i 个人的高度。 一个人能 看到 他右边另一个人…

计算机网络 运输层下 | TCP概述 可靠传输 流量控制 拥塞控制 连接管理

文章目录 3 运输层主要协议 TCP 概述3.1 TCP概述 特点3.2 TCP连接RSVP资源预留协议 4 TCP可靠传输4.1 可靠传输工作原理4.1.1 停止等待协议4.1.2 连续ARQ协议 4.2 TCP可靠通信的具体实现4.2.1 以字节为单位的滑动窗口4.2.2 超时重传时间的选择4.2.3 选择确认SACK 5 TCP的流量控…

边缘计算有哪些常用场景?TSINGSEE边缘AI视频分析技术行业解决方案

随着ChatGPT生成式人工智能的爆发&#xff0c;AI技术在业界又掀起一波新浪潮。值得关注的是&#xff0c;边缘AI智能也在AI人工智能技术进步的基础上得到了快速发展。IDC跟踪报告数据显示&#xff0c;2021年我国的边缘计算服务器整体市场规模达到33.1亿美元&#xff0c;预计2020…

2023年中国法拍房用户画像和数据分析

法拍房主要平台 法拍房主要平台有3家&#xff0c;分别是阿里、京东和北交互联平台。目前官方认定纳入网络司法拍卖的平台共有7家&#xff0c;其中阿里资产司法拍卖平台的挂拍量最大。 阿里法拍房 阿里法拍房数据显示2017年&#xff0c;全国法拍房9000套&#xff1b;2018年&a…

HuatuoGPT模型介绍

文章目录 HuatuoGPT 模型介绍LLM4Med&#xff08;医疗大模型&#xff09;的作用ChatGPT 存在的问题HuatuoGPT的特点ChatGPT 与真实医生的区别解决方案用于SFT阶段的混合数据基于AI反馈的RL 评估单轮问答多轮问答人工评估 HuatuoGPT 模型介绍 HuatuoGPT&#xff08;华佗GPT&…

Web请求与响应

目录 Postman Postman简介 Postman的使用 请求 简单参数 实体参数 数组参数 集合参数 日期参数 Json参数 路径参数 响应 ResponseBody 统一响应结果 Postman Postman简介 postman是一款功能强大的网页调试与发送网页http请求的Chrome插件&#xff0c;常用于进行…

故障排查:shell脚本输出乱码

博客主页&#xff1a;https://tomcat.blog.csdn.net 博主昵称&#xff1a;农民工老王 主要领域&#xff1a;Java、Linux、K8S 期待大家的关注&#x1f496;点赞&#x1f44d;收藏⭐留言&#x1f4ac; 目录 故障详情故障原因解决方法iconv命令介绍 故障详情 最近的工作中遇到一…

C语言:指向数组的指针和指向数组元素的指针

相关阅读 C语言https://blog.csdn.net/weixin_45791458/category_12423166.html?spm1001.2014.3001.5482 指向数组的指针和指向数组元素的指针常常被混淆&#xff0c;或者笼统地被称为数组指针&#xff0c;但它们之间是有差别的&#xff0c;本文就将对此进行讨论。 下面的代码…

Java设计模式:工厂模式(简单工厂模式、工厂方法模式、抽象工厂模式)

❤ 作者主页&#xff1a;欢迎来到我的技术博客&#x1f60e; ❀ 个人介绍&#xff1a;大家好&#xff0c;本人热衷于Java后端开发&#xff0c;欢迎来交流学习哦&#xff01;(&#xffe3;▽&#xffe3;)~* &#x1f34a; 如果文章对您有帮助&#xff0c;记得关注、点赞、收藏、…

第五讲观测值中与卫星、接收机有关的误差 第六讲观测值中与信号传播路径有关的误差以及电离层、对流层相关模型 | GNSS(RTK)课程学习笔记day3

说明&#xff1a;以下笔记来自计算机视觉life吴桐老师课程&#xff1a;从零掌握GNSS、RTK定位[链接]&#xff0c;从零掌握RTKLIB[链接]。非原创&#xff01;且笔记仅供自身与大家学习使用&#xff0c;无利益目的。 第五讲 观测值中与卫星、接收机有关的误差 卫星轨道误差 由卫…

Kafka-Kafka核心参数详解

Kafka的HighLevel API使用是非常简单的&#xff0c;所以梳理模型时也要尽量简单化&#xff0c;主线清晰&#xff0c;细节慢慢扩展。 Kafka提供了两套客户端API&#xff0c;HighLevel API和LowLevel API。 HighLevel API封装了kafka的运行细节&#xff0c;使用起来比较简单&…

jQuery实现轮播图代码

简述 一个简单的jQuery轮播图代码,首先,定义了一个slideshow-container的div容器,其中包含了所有轮播图幻灯片。每个幻灯片都包含一个mySlides的类名,并且使用CSS将其隐藏。然后,使用JavaScript代码来控制幻灯片的显示和隐藏。在showSlides()函数中,遍历所有幻灯片并将它…

【项目管理】redmine

Redmine是用Ruby开发的基于web的项目管理软件&#xff0c;是用ROR框架开发的一套跨平台项目管理系统&#xff0c;据说是源于Basecamp的ror版而来&#xff0c;支持多种数据库&#xff0c;有不少自己独特的功能&#xff0c;例如提供wiki、新闻台等&#xff0c;还可以集成其他版本…

Flutter实现丝滑的滑动删除、移动排序等-Dismissible控件详解

文章目录 Dismissible 简介使用场景常用属性基本用法举例注意事项 Dismissible 简介 Dismissible 是 Flutter 中用于实现可滑动删除或拖拽操作的一个有用的小部件。主要用于在用户对列表项或任何其他可滑动的元素执行删除或拖动操作时&#xff0c;提供一种简便的实现方式。 使…