当前位置: 首页 > news >正文

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.二叉排序树的删除

二叉排序树的删除情况比较复杂,有下面三种情况需要考虑

  1. 删除叶子节点 (比如:2, 5, 9, 12)
  2. 删除只有一颗子树的节点 (比如:1)
  3. 删除有两颗子树的节点. (比如:7, 3,10 )
  4. 操作的思路分析
    在这里插入图片描述

//对删除结点的各种情况的思路分析:
第一种情况:
删除叶子节点 (比如: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)&#xff0c;要求能够高效的完成对数据的查询和添加 2.解决方案分析 使用数组 数组未排序&#xff0c; 优点&#xff1a;直接在数组尾添加&#xff0c;速度快。 缺点&#xff1a;查找速度慢. [示意图] 数组排序&#xf…...

聊一聊 gRPC 的四种通信模式

温馨提示&#xff1a;本文需要结合上一篇 gRPC 文章一起食用&#xff0c;否则可能看不懂。 前面一篇文章松哥和大家聊了 gRPC 的基本用法&#xff0c;今天我们再来稍微深入一点点&#xff0c;来看下 gRPC 中四种不同的通信模式。 gRPC 中四种不同的通信模式分别是&#xff1a;…...

科技云报道:开源真的香,风险知多少?

科技云报道原创。 过去几年&#xff0c;开源界一片火热&#xff0c;开源软件技术已全面进军操作系统、云原生、人工智能、大数据、半导体、物联网等行业领域。 数据显示&#xff0c;我国超九成企业在使用或正计划使用开源技术。 与此同时&#xff0c;全球各大开源组织相继兴…...

国产化适配迁移记录

国产化适配迁移记录 本项目基于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 日&#xff0c;Apache 软件基金会 (ASF) 官方正式宣布Apache bRPC 正式毕业&#xff0c;成为 Apache的顶级项目。 我听到这个消息是挺开心的&#xff0c;毕竟是又一款由国人主导的apche顶级项目&#xff0c;再次证明国内在开源界正在发挥越来越重要的作用。 …...

多数据库学习之GBase8s查询数据库表元信息常用SQL

多数据库学习之GBase8s查询数据库表元信息常用SQL简介常用SQL创建用户创建数据库及模式获取表元数据其他参考链接简介 背景介绍 GBase 8t是基于IBM informix源代码、编译和测试体系自主研发的交易型数据库产品。 南大通用安全数据库管理系统&#xff08;简称 GBase 8s&#xff…...

Jetpack之Lifecycle应用与源码分析

Build lifecycle-aware components that can adjust behavior based on the current lifecycle state of an activity or fragment. 上面是源于官网的定义&#xff0c;简单翻译就是说Lifecycle的作用就是基于当前的Activity或者Fragment的生命周期当前状态构建可感知生命周期的…...

Python序列类型之集合

&#x1f490;&#x1f490;&#x1f490;欢迎来到小十一的博客&#xff01;&#xff01;&#xff01; &#x1f3af;博客主页&#xff1a;&#x1f3af;程序员小十一的博客 &#x1f680;博客专栏&#xff1a;&#x1f680;Python入门基础语法 &#x1f337;欢迎关注&#xff…...

java 自定义json解析注解 复杂json解析

java 自定义json解析注解 复杂json解析 工具类 目录java 自定义json解析注解 复杂json解析 工具类1.背景2、需求-各式各样的json一、一星难度json【json对象中不分层】二、二星难度json【json对象中出现层级】三、三星难度json【json对象中存在数组】四、四星难度json【json对象…...

Vue3配置路由(vue-router)

文章目录前言一、配置路由&#xff08;vue-router&#xff09;1、安装路由2、新建页面3、创建路由配置文件4.特殊报错&#xff01;前言 紧接上篇文章&#xff0c;vue3的配置与vue2是有所差别的&#xff0c;本文就讲述了如何配置&#xff0c;如果本文对你有所帮助请三连支持博主…...

【代码随想录二刷】Day9-字符串-C++

代码随想录二刷Day9 今日任务 28.找出字符串中第一个匹配项的下标 459.重复的子字符串 字符串总结 双指针总结 语言&#xff1a;C KMP 链接&#xff1a;https://programmercarl.com/0459.重复的子字符串.html#kmp 用处&#xff1a;当出现字符串不匹配时&#xff0c;可以利…...

google colab上如何下载bert相关模型

首先要知道模型的地址 tensorflow版本的模型&#xff1a; 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)

预期效果&#xff1a;&#xff08;借助iview-ui的在线体验页面示意一下&#xff09; 项目中只有一部分页面需要缓存&#xff0c;且存在多级路由的页面。每打开一个菜单&#xff0c;就会新增一个 Tab标签&#xff0c;只要 Tab标签不关闭&#xff0c;对应的页面就会被缓存&#x…...

C++STL剖析(四)—— stack和queue的概念和使用

文章目录1. stack的介绍2. stack的构造3. stack的使用&#x1f351; push&#x1f351; top&#x1f351; pop&#x1f351; empty&#x1f351; size&#x1f351; swap&#x1f351; emplace4. queue的介绍5. queue的构造6. queue的使用&#x1f351; push&#x1f351; size…...

流浪地球 | 建筑人是如何看待小破球里的黑科技的?

大家好&#xff0c;这里是建模助手。 想问问大家今年贺岁档&#xff0c;都跟上没有&#xff0c;今天请允许我蹭一下热点表达一下作为一个科幻迷的爱国之情。 抛开大刘的想象力、各种硬核科技&以及大国情怀不提&#xff0c;破球2中的传承还是让小编很受感动&#xff0c;无…...

软中断在bottom-half中调用

https://www.bilibili.com/read/cv20785285/简介软中断可以在两个位置得到机会执行&#xff1a;硬中断返回前 irq_exit中断下半部 Bottom-half Enable后情景分析情景1spin_unlock_bh__raw_spin_unlock_bh__local_bh_enable_ip 打开Bottom-half&#xff0c;并让softirq有机会…...

GEE遥感云大数据在林业中的应用

近年来遥感技术得到了突飞猛进的发展&#xff0c;航天、航空、临近空间等多遥感平台不断增加&#xff0c;数据的空间、时间、光谱分辨率不断提高&#xff0c;数据量猛增&#xff0c;遥感数据已经越来越具有大数据特征。遥感大数据的出现为相关研究提供了前所未有的机遇&#xf…...

Apollo架构篇 - 客户端架构

前言 本文基于 Apollo 1.8.0 版本展开分析。 客户端 使用 Apollo 支持 API 方式和 Spring 整合两种方式。 API 方式 API 方式是最简单、高效使用使用 Apollo 配置的方式&#xff0c;不依赖 Spring 框架即可使用。 获取命名空间的配置 // 1、获取默认的命名空间的配置 C…...

JVM调优最全面的成长 :参数详解+垃圾算法+示例展示+类文件到源码+面试问题

目录1.优秀的Java开发者1.1 什么是Java&#xff1f;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驱动常用函数

以下为一些常见用户态函数在内核中的替代&#xff0c;包括头文件和函数声明&#xff1a;1、动态申请内存&#xff1a;linux/vmalloc.hvoid *vmalloc(unsigned long size);void vfree(const void *addr);2、字符串操作&#xff1a;linux/string.hvoid * memset(void *,int,__ker…...

Flowable进阶学习(九)数据对象DataObject、租户Tenant、接收任务ReceiveTask

文章目录一、数据对象DataObject二、租户 Tenant三、接收任务 ReceiveTask案例一、数据对象DataObject DataObject可以⽤来定义⼀些流程的全局属性。 绘制流程图&#xff0c;并配置数据对象&#xff08;不需要选择任意节点&#xff09; 2. 编码与测试 /*** 部署流程*/ Test…...

C语言实现五子棋(n子棋)

五子棋的历史背景&#xff1a; 五子棋起源于中国&#xff0c;是全国智力运动会竞技项目之一&#xff0c;是一种两人对弈的纯策略型棋类游戏。双方分别使用黑白两色的棋子&#xff0c;下在棋盘直线与横线的交叉点上&#xff0c;先形成五子连珠者获胜。五子棋容易上手&#xff0c…...

OpenStack云平台搭建(2) | 安装Keystone

目录 1、登录数据库配置 2、数据库导入Keystone表 3、配置http服务 4、创建域、用户 5、创建脚本 Keystone&#xff08;OpenStack Identity Service&#xff09;是 OpenStack 框架中负责管理身份验证、服务访问规则和服务令牌功能的组件。下面我们进行Keystone的安装部署 1…...

基于javaFX的固定资产管理系统

1. 总体设计 本系统分为登录模块、资产管理模块、资产登记模块和信息展示模块共四个模块。 登录模块的主要功能是&#xff1a;管理员通过登录模块登录本系统&#xff1b; 资产管理模块的主要功能有&#xff1a;修改、删除系统中的固定资产&#xff1b; 在资产登记模块中&#…...

板子登录和挂载问题记录

ubuntu登录板子问题 ssh登录ssh 10.1.3.15&#xff0c;显示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系统调用&#xff1a;open write read close Linux自带的工具&#xf…...

源码分析Spring解决循环依赖的过程

循环依赖是之前很爱问的一个面试题&#xff0c;最近不咋问了&#xff0c;但是梳理Spring解决循环依赖的源码&#xff0c;会让我们对Spring创建bean的流程有一个清晰的认识&#xff0c;有必要搞一搞。开始搞之前&#xff0c;先参考了这个老哥写的文章&#xff0c;对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程序集&#xff0c;但是当尝试在构造函数节点中加载这些程序集时&#xff0c;却收到LabVIEW消息显示: 所选文件不是.NET程序集&#xff0c;所属类型库或自动化可执行文件。所以想确认是否可以在…...

Fluent Python 笔记 第 2 章 序列构成的数组

2.1 内置类型序列概览 容器序列&#xff08;能存放不同类型的数据&#xff09;&#xff1a;(作者分的类) list、tuple 和 collections.deque扁平序列&#xff08;只能容纳一种类型&#xff09;&#xff1a; str、byes、bytearray、memoryview 和 array.array可变&#xff1a…...

句子扩充法

人&#xff0c;物&#xff0c;时&#xff0c;地&#xff0c;事 什么人和什么物在什么时间什么地点发生了什么事。 思维导图&#xff1a;以人为中心&#xff0c;人具有客观能动性。 例如&#xff1a;秋燕南飞。 扩展为&#xff1a; 盘旋在洞庭湖上方的大雁渐渐消失了。“它们都…...

网站建设与管理模拟题1/小型培训机构管理系统

从HTML被发明开始&#xff0c;样式就以各种形式存在。不同的浏览器结合它们各自的样式语言为用户提供页面效果的控制。最初的HTML只包含很少的显示属性。随着HTML的成长&#xff0c;为了满足页面设计者的要求&#xff0c;HTML添加了很多显示功能。但是随着这些功能的增加&#…...

广西建设科技与建筑节能协会网站/正版google下载

业界专家Edward Tufte提出了数据墨水(Data Ink)的概念&#xff0c;来指导表格数据显示和表格设计。 那什么是数据墨水呢&#xff1f;数据墨水是指那些用来表达数据的像素。如果把它抹掉&#xff0c;显示的数据信息就会改变。数据墨水的概念是尽量增加数据墨水对非数据墨水的比例…...

杭州百度网站建设/手机刷网站排名软件

1、jenkins服务器和各节点服务器之间&#xff0c;要配置基于密钥的登录 (本实例基于www用户)(省略)2、创建相应的目录&#xff0c;并授权属主属组为www用户/deploy/tmp 临时目录/deploy/tar 存放打包后的目录/opt/wwwroot 远程服务器目录/web/ 网站目录3、配置jenkins![](https…...

常德网站建设哪家快/站长统计网站

对应的问题&#xff1a; 在用tensorflow构造自己的损失函数时&#xff0c;经常会涉及到复杂的矩阵乘法。而这些矩阵乘法本来并不复杂&#xff0c; 比如只是简单的 维度为ABA\times BAB 的矩阵 X\mathbf{X}X 和 维度为 BCB\times CBC的矩阵Y\mathbf{Y}Y相乘。 但是由于在深度学…...

网络营销管理方案/搜索引擎优化百度百科

概要P/Invoke的机制让我们能在托管环境下使用原先已实现的Native Code。本文主要讨论的是P/Invoke中的参数传递和.NET CF的一些不同于完整版本的 .NET Fx之处&#xff0c;最后介绍了如何提高P/invoke的效率 Keywords.NET Compact Framework, Windows Mobile, P/Invoke ,data ma…...

房山 网站建设/短视频剪辑培训班速成

留存折损—–两个不同节点的留存之间的比值&#xff0c;用于判断留下用户的留存情况&#xff0c;即真实用户的留存。 换一种维度去分析留存&#xff0c;不拘泥于留存的绝对值&#xff0c;将留存统一化&#xff0c;提炼客观的参考标准。 常见的留存疑惑&#xff1a;** 我的游…...