java二叉排序树
1.先看一个需求
给你一个数列 (7, 3, 10, 12, 5, 1, 9),要求能够高效的完成对数据的查询和添加
2.解决方案分析
使用数组
数组未排序, 优点:直接在数组尾添加,速度快。 缺点:查找速度慢. [示意图]
数组排序,优点:可以使用二分查找,查找速度快,缺点:为了保证数组有序,在添加新数据时,找到插入位
置后,后面的数据需整体移动,速度慢。[示意图]
使用链式存储-链表
不管链表是否有序,查找速度都慢,添加数据速度比数组快,不需要数据整体移动。[示意图]
使用二叉排序树
3.二叉排序树介绍
二叉排序树:BST: (Binary Sort(Search) Tree), 对于二叉排序树的任何一个非叶子节点,要求左子节点的值比当
前节点的值小,右子节点的值比当前节点的值大。
特别说明:如果有相同的值,可以将该节点放在左子节点或右子节点
比如针对前面的数据 (7, 3, 10, 12, 5, 1, 9) ,对应的二叉排序树为
4.二叉排序树创建和遍历
一个数组创建成对应的二叉排序树,并使用中序遍历二叉排序树,比如: 数组为 Array(7, 3, 10, 12, 5, 1, 9) , 创
建成对应的二叉排序树为 :
5.二叉排序树的删除
二叉排序树的删除情况比较复杂,有下面三种情况需要考虑
- 删除叶子节点 (比如:2, 5, 9, 12)
- 删除只有一颗子树的节点 (比如:1)
- 删除有两颗子树的节点. (比如:7, 3,10 )
- 操作的思路分析
//对删除结点的各种情况的思路分析:
第一种情况:
删除叶子节点 (比如:2, 5, 9, 12)
思路
(1) 需求先去找到要删除的结点 targetNode
(2) 找到 targetNode 的 父结点 parent
(3) 确定 targetNode 是 parent 的左子结点 还是右子结点
(4) 根据前面的情况来对应删除
左子结点 parent.left = null
右子结点 parent.right = null;
第二种情况: 删除只有一颗子树的节点 比如 1
思路
(1) 需求先去找到要删除的结点 targetNode
(2) 找到 targetNode 的 父结点 parent
(3) 确定 targetNode 的子结点是左子结点还是右子结点
(4) targetNode 是 parent 的左子结点还是右子结点
(5) 如果 targetNode 有左子结点
5. 1 如果 targetNode 是 parent 的左子结点
parent.left = targetNode.left;
5.2 如果 targetNode 是 parent 的右子结点
parent.right = targetNode.left;
(6) 如果 targetNode 有右子结点
6.1 如果 targetNode 是 parent 的左子结点
parent.left = targetNode.right;
6.2 如果 targetNode 是 parent 的右子结点
parent.right = targetNode.right
情况三 : 删除有两颗子树的节点. (比如:7, 3,10 )
思路
(1) 需求先去找到要删除的结点 targetNode
(2) 找到 targetNode 的 父结点 parent
(3) 从 targetNode 的右子树找到最小的结点
(4) 用一个临时变量,将 最小结点的值保存 temp = 11
(5) 删除该最小结点
(6) targetNode.value = temp
6.二叉排序树删除结点的代码实现:
public class BinarySortTreeDemo {public static void main(String[] args) {// TODO Auto-generated method stubint arr[] = { 7, 3, 10, 12, 5, 1, 9, 2 };BinarySortTree binarySortTree = new BinarySortTree();// 循环的添加结点到二叉树for (int i = 0; i < arr.length; i++) {binarySortTree.add(new Node(arr[i]));}// 中序遍历二叉排序树System.out.println("中序遍历二叉排序树");binarySortTree.infixOrder();// 1,3,5,7,9,10,12// 测试一下删除叶子节点
// binarySortTree.delNode(2);
// binarySortTree.delNode(1);binarySortTree.delNode(7);System.out.println("删除结点后");binarySortTree.infixOrder();}}//创建二叉排序树
class BinarySortTree {private Node root;// 查找要删除的结点public Node search(int value) {if (root == null) {return null;} else {return root.search(value);}}// 查找父结点public Node searchParent(int value) {if (root == null) {return null;} else {return root.searchParent(value);}}// 编写方法// 1.返回以node为根节点的二叉排序树的最小节点的值// 2.删除以node为根节点的二叉排序树的最小节点的值/*** * @param node 传入的结点(当作二叉排序树的根节点)* @return 返回的以node为结点的二叉树的最小结点的值*/public int delRightTreeMin(Node node) {Node target = node;// 循环的查找左节点,就会找到最小值while (target.left != null) {target = target.left;}// 这时target就指向了最小节点// 删除最小节点delNode(target.value);return target.value;}// 删除结点public void delNode(int value) {if (root == null) {return;} else {// 1.需要先去找到要删除的结点 targetNodeNode targetNode = search(value);// 如果没有找到要删除的结点if (targetNode == null) {return;}// 如果我们发现targetNode没有父结点if (root.left == null && root.right == null) {root = null;return;}// 去查找targetNode的父结点Node parent = searchParent(value);// 如果要删除的节点是叶子节点if (targetNode.left == null && targetNode.right == null) {// 判断targetNode是父结点的左指结点还是右子节点if (parent.left != null && parent.left.value == value) {// 是左指结点parent.left = null;} else if (parent.right != null && parent.right.value == value) {// 是右子结点parent.right = null;}} else if (targetNode.left != null && targetNode.right != null) {// 删除有两颗子树的节点int minVal = delRightTreeMin(targetNode.right);targetNode.value = minVal;} else {// 删除只有一颗子树的结点// 如果要删除的结点有左指结点if (targetNode.left != null) {// 如果targetNode是parent的左指结点if (parent.left.value == value) {parent.left = targetNode.left;} else {// targetNode是parent的右子结点parent.right = targetNode.left;}} else {// 如果要删除的节点有右子结点// 如果targetNode是parent的左指结点if (parent.left.value == value) {parent.left = targetNode.right;} else {// 如果targetNode是parent的右指结点parent.right = targetNode.right;}}}}}// 添加结点方法public void add(Node node) {if (root == null) {root = node;// 如果root为空则直接让root指向node} else {root.add(node);}}// 中序遍历public void infixOrder() {if (root != null) {root.infixOrder();} else {System.out.println("二叉排序树为空,不能遍历");}}
}//创建Node结点
class Node {int value;Node left;Node right;public Node(int value) {super();this.value = value;}// 查找要删除的结点/*** * @param value 希望删除的结点的值* @return 如果找到返回该节点,否则返回null*/public Node search(int value) {if (value == this.value) {return this;} else if (value < this.value) {// 如果查找的值小于当前节点,向左子树递归查找// 如果左子结点为空if (this.left == null) {return null;}return this.left.search(value);} else {// 如果查找的值不小于当前节点,向右子树递归查找if (this.right == null) {return null;}return this.right.search(value);}}// 查找要删除该节点的父节点/*** * @param value 要找到的结点的值* @return 返回的是要删除的结点的父节点,如果没有就返回null*/public Node searchParent(int value) {// 如果当前结点就是要删除的结点的父结点,就返回if ((this.left != null && this.left.value == value) || (this.right != null && this.right.value == value)) {return this;} else {// 如果要查找的值小于当前节点的值,并且当前节点的左指结点不为空if (value < this.value && this.left != null) {return this.left.searchParent(value);// 向左子树递归查找} else if (value >= this.value && this.right != null) {return this.right.searchParent(value);// 向右子树递归查找} else {return null;// 没有找到父结点}}}@Overridepublic String toString() {return "Node [value=" + value + "]";}// 添加结点方法// 递归的方式添加结点,需要满足二叉排序树的要求public void add(Node node) {if (node == null) {return;}// 判断传入结点的值,和当前子树的根结点的值关系if (node.value < this.value) {// 如果当前节点左子节点为nullif (this.left == null) {this.left = node;} else {// 递归的向左子树添加this.left.add(node);}} else {// 添加的结点的值大于当前节点的值if (this.right == null) {this.right = node;} else {// 递归向右子树添加this.right.add(node);}}}// 中序遍历public void infixOrder() {if (this.left != null) {this.left.infixOrder();}System.out.println(this);if (this.right != null) {this.right.infixOrder();}}
}
相关文章:
java二叉排序树
1.先看一个需求 给你一个数列 (7, 3, 10, 12, 5, 1, 9),要求能够高效的完成对数据的查询和添加 2.解决方案分析 使用数组 数组未排序, 优点:直接在数组尾添加,速度快。 缺点:查找速度慢. [示意图] 数组排序…...
聊一聊 gRPC 的四种通信模式
温馨提示:本文需要结合上一篇 gRPC 文章一起食用,否则可能看不懂。 前面一篇文章松哥和大家聊了 gRPC 的基本用法,今天我们再来稍微深入一点点,来看下 gRPC 中四种不同的通信模式。 gRPC 中四种不同的通信模式分别是:…...
科技云报道:开源真的香,风险知多少?
科技云报道原创。 过去几年,开源界一片火热,开源软件技术已全面进军操作系统、云原生、人工智能、大数据、半导体、物联网等行业领域。 数据显示,我国超九成企业在使用或正计划使用开源技术。 与此同时,全球各大开源组织相继兴…...
国产化适配迁移记录
国产化适配迁移记录 本项目基于RuoYi-Vue的框架进行迁移。目前已完成覆盖测试暂无其他问题。 国产化环境 名称版本达梦数据库DmJdbcDriver18 8.1.2.144通用mapper – tk.mybatismapper-spring-boot-starter 4.2.5<!-- 达梦数据库--><dependency><groupId>…...
又一国产开源项目走向世界,百度RPC框架Apache bRPC正式成为ASF顶级项目
2023 年 1 月 26 日,Apache 软件基金会 (ASF) 官方正式宣布Apache bRPC 正式毕业,成为 Apache的顶级项目。 我听到这个消息是挺开心的,毕竟是又一款由国人主导的apche顶级项目,再次证明国内在开源界正在发挥越来越重要的作用。 …...
多数据库学习之GBase8s查询数据库表元信息常用SQL
多数据库学习之GBase8s查询数据库表元信息常用SQL简介常用SQL创建用户创建数据库及模式获取表元数据其他参考链接简介 背景介绍 GBase 8t是基于IBM informix源代码、编译和测试体系自主研发的交易型数据库产品。 南大通用安全数据库管理系统(简称 GBase 8sÿ…...
Jetpack之Lifecycle应用与源码分析
Build lifecycle-aware components that can adjust behavior based on the current lifecycle state of an activity or fragment. 上面是源于官网的定义,简单翻译就是说Lifecycle的作用就是基于当前的Activity或者Fragment的生命周期当前状态构建可感知生命周期的…...
Python序列类型之集合
💐💐💐欢迎来到小十一的博客!!! 🎯博客主页:🎯程序员小十一的博客 🚀博客专栏:🚀Python入门基础语法 🌷欢迎关注ÿ…...
java 自定义json解析注解 复杂json解析
java 自定义json解析注解 复杂json解析 工具类 目录java 自定义json解析注解 复杂json解析 工具类1.背景2、需求-各式各样的json一、一星难度json【json对象中不分层】二、二星难度json【json对象中出现层级】三、三星难度json【json对象中存在数组】四、四星难度json【json对象…...
Vue3配置路由(vue-router)
文章目录前言一、配置路由(vue-router)1、安装路由2、新建页面3、创建路由配置文件4.特殊报错!前言 紧接上篇文章,vue3的配置与vue2是有所差别的,本文就讲述了如何配置,如果本文对你有所帮助请三连支持博主…...
【代码随想录二刷】Day9-字符串-C++
代码随想录二刷Day9 今日任务 28.找出字符串中第一个匹配项的下标 459.重复的子字符串 字符串总结 双指针总结 语言:C KMP 链接:https://programmercarl.com/0459.重复的子字符串.html#kmp 用处:当出现字符串不匹配时,可以利…...
google colab上如何下载bert相关模型
首先要知道模型的地址 tensorflow版本的模型: https://storage.googleapis.com/bert_models/2018_10_18/cased_L-12_H-768_A-12.zip https://storage.googleapis.com/bert_models/2018_11_03/chinese_L-12_H-768_A-12.zip pytorch版本的模型 ‘bert-base-cased’: …...
Vue2.0页面缓存机制联合页面标签的交互(keep-alive + router)
预期效果:(借助iview-ui的在线体验页面示意一下) 项目中只有一部分页面需要缓存,且存在多级路由的页面。每打开一个菜单,就会新增一个 Tab标签,只要 Tab标签不关闭,对应的页面就会被缓存&#x…...
C++STL剖析(四)—— stack和queue的概念和使用
文章目录1. stack的介绍2. stack的构造3. stack的使用🍑 push🍑 top🍑 pop🍑 empty🍑 size🍑 swap🍑 emplace4. queue的介绍5. queue的构造6. queue的使用🍑 push🍑 size…...
流浪地球 | 建筑人是如何看待小破球里的黑科技的?
大家好,这里是建模助手。 想问问大家今年贺岁档,都跟上没有,今天请允许我蹭一下热点表达一下作为一个科幻迷的爱国之情。 抛开大刘的想象力、各种硬核科技&以及大国情怀不提,破球2中的传承还是让小编很受感动,无…...
软中断在bottom-half中调用
https://www.bilibili.com/read/cv20785285/简介软中断可以在两个位置得到机会执行:硬中断返回前 irq_exit中断下半部 Bottom-half Enable后情景分析情景1spin_unlock_bh__raw_spin_unlock_bh__local_bh_enable_ip 打开Bottom-half,并让softirq有机会…...
GEE遥感云大数据在林业中的应用
近年来遥感技术得到了突飞猛进的发展,航天、航空、临近空间等多遥感平台不断增加,数据的空间、时间、光谱分辨率不断提高,数据量猛增,遥感数据已经越来越具有大数据特征。遥感大数据的出现为相关研究提供了前所未有的机遇…...
Apollo架构篇 - 客户端架构
前言 本文基于 Apollo 1.8.0 版本展开分析。 客户端 使用 Apollo 支持 API 方式和 Spring 整合两种方式。 API 方式 API 方式是最简单、高效使用使用 Apollo 配置的方式,不依赖 Spring 框架即可使用。 获取命名空间的配置 // 1、获取默认的命名空间的配置 C…...
JVM调优最全面的成长 :参数详解+垃圾算法+示例展示+类文件到源码+面试问题
目录1.优秀的Java开发者1.1 什么是Java?1.2 编程语言1.3 计算机[硬件]能够懂的语言1.3.1 计算机发展史1.3.2 计算机体系结构1.3.3 计算机处理数据过程1.3.4 机器语言1.3.5 不同厂商的CPU1.3.6 操作系统1.3.7 汇编语言1.3.8 高级语言1.3.9 编译型和解释型1.3.9.1 编译…...
linux驱动常用函数
以下为一些常见用户态函数在内核中的替代,包括头文件和函数声明:1、动态申请内存:linux/vmalloc.hvoid *vmalloc(unsigned long size);void vfree(const void *addr);2、字符串操作:linux/string.hvoid * memset(void *,int,__ker…...
Flowable进阶学习(九)数据对象DataObject、租户Tenant、接收任务ReceiveTask
文章目录一、数据对象DataObject二、租户 Tenant三、接收任务 ReceiveTask案例一、数据对象DataObject DataObject可以⽤来定义⼀些流程的全局属性。 绘制流程图,并配置数据对象(不需要选择任意节点) 2. 编码与测试 /*** 部署流程*/ Test…...
C语言实现五子棋(n子棋)
五子棋的历史背景: 五子棋起源于中国,是全国智力运动会竞技项目之一,是一种两人对弈的纯策略型棋类游戏。双方分别使用黑白两色的棋子,下在棋盘直线与横线的交叉点上,先形成五子连珠者获胜。五子棋容易上手,…...
OpenStack云平台搭建(2) | 安装Keystone
目录 1、登录数据库配置 2、数据库导入Keystone表 3、配置http服务 4、创建域、用户 5、创建脚本 Keystone(OpenStack Identity Service)是 OpenStack 框架中负责管理身份验证、服务访问规则和服务令牌功能的组件。下面我们进行Keystone的安装部署 1…...
基于javaFX的固定资产管理系统
1. 总体设计 本系统分为登录模块、资产管理模块、资产登记模块和信息展示模块共四个模块。 登录模块的主要功能是:管理员通过登录模块登录本系统; 资产管理模块的主要功能有:修改、删除系统中的固定资产; 在资产登记模块中&#…...
板子登录和挂载问题记录
ubuntu登录板子问题 ssh登录ssh 10.1.3.15,显示No route to host 则尝试在板子上ping 本机ip 试一下 挂载 本地机器vim /etc/export编辑此内容并保存 /exports_0209/tda4_build *(rw,no_root_squash,nohide,insecure,no_subtree_check,async)1.挂载nfs方法 mou…...
二、Linux文件 - Open函数讲解实战
目录 1.Open函数讲解 2.open函数实战 2.1 man 1 ls 查询Shell命令 2.2 man 2 open 查看系统调用函数 2.3项目实战 2.3.1O_RDWR和O_CREAT 2.3.2O_APPEND的用法 1.Open函数讲解 高频使用的Linux系统调用:open write read close Linux自带的工具…...
源码分析Spring解决循环依赖的过程
循环依赖是之前很爱问的一个面试题,最近不咋问了,但是梳理Spring解决循环依赖的源码,会让我们对Spring创建bean的流程有一个清晰的认识,有必要搞一搞。开始搞之前,先参考了这个老哥写的文章,对Spring处理循…...
LabVIEW中加载.NET 2.0,3.0和3.5程序集
LabVIEW中加载.NET 2.0,3.0和3.5程序集已使用.NETFramework 2.0,3.0或3.5创建了.NET程序集,但是当尝试在构造函数节点中加载这些程序集时,却收到LabVIEW消息显示: 所选文件不是.NET程序集,所属类型库或自动化可执行文件。所以想确认是否可以在…...
Fluent Python 笔记 第 2 章 序列构成的数组
2.1 内置类型序列概览 容器序列(能存放不同类型的数据):(作者分的类) list、tuple 和 collections.deque扁平序列(只能容纳一种类型): str、byes、bytearray、memoryview 和 array.array可变:…...
句子扩充法
人,物,时,地,事 什么人和什么物在什么时间什么地点发生了什么事。 思维导图:以人为中心,人具有客观能动性。 例如:秋燕南飞。 扩展为: 盘旋在洞庭湖上方的大雁渐渐消失了。“它们都…...
网站建设与管理模拟题1/小型培训机构管理系统
从HTML被发明开始,样式就以各种形式存在。不同的浏览器结合它们各自的样式语言为用户提供页面效果的控制。最初的HTML只包含很少的显示属性。随着HTML的成长,为了满足页面设计者的要求,HTML添加了很多显示功能。但是随着这些功能的增加&#…...
广西建设科技与建筑节能协会网站/正版google下载
业界专家Edward Tufte提出了数据墨水(Data Ink)的概念,来指导表格数据显示和表格设计。 那什么是数据墨水呢?数据墨水是指那些用来表达数据的像素。如果把它抹掉,显示的数据信息就会改变。数据墨水的概念是尽量增加数据墨水对非数据墨水的比例…...
杭州百度网站建设/手机刷网站排名软件
1、jenkins服务器和各节点服务器之间,要配置基于密钥的登录 (本实例基于www用户)(省略)2、创建相应的目录,并授权属主属组为www用户/deploy/tmp 临时目录/deploy/tar 存放打包后的目录/opt/wwwroot 远程服务器目录/web/ 网站目录3、配置jenkins![](https…...
常德网站建设哪家快/站长统计网站
对应的问题: 在用tensorflow构造自己的损失函数时,经常会涉及到复杂的矩阵乘法。而这些矩阵乘法本来并不复杂, 比如只是简单的 维度为ABA\times BAB 的矩阵 X\mathbf{X}X 和 维度为 BCB\times CBC的矩阵Y\mathbf{Y}Y相乘。 但是由于在深度学…...
网络营销管理方案/搜索引擎优化百度百科
概要P/Invoke的机制让我们能在托管环境下使用原先已实现的Native Code。本文主要讨论的是P/Invoke中的参数传递和.NET CF的一些不同于完整版本的 .NET Fx之处,最后介绍了如何提高P/invoke的效率 Keywords.NET Compact Framework, Windows Mobile, P/Invoke ,data ma…...
房山 网站建设/短视频剪辑培训班速成
留存折损—–两个不同节点的留存之间的比值,用于判断留下用户的留存情况,即真实用户的留存。 换一种维度去分析留存,不拘泥于留存的绝对值,将留存统一化,提炼客观的参考标准。 常见的留存疑惑:** 我的游…...