二叉搜索树的基本操作(最全面)

目录

二叉搜索的定义:

节点类:

查找关键词对应的值:

非递归

递归:

查找最小关键词对应的值:

方法一:

方法二:

查找最大关键词对应的值:

方法一:

方法二:

存贮关键词对应的值:

查找关键词的前驱值:

查找关键词对应的后继值: 

删除节点:

非递归:

递归:

范围

1.小于某值的范围

2.大于某值的范围

3.在区间的值


二叉搜索的定义:

1.key属性值不能重复

2.左子树所有节点的key值都小于根节点的key值

3.右子树所有节点的key值都要大于根节点的key值

节点类:

 static class BSTNode{int key;//key必须能够进行大小比较 创建一个接口comparableObject value;BSTNode left;BSTNode right;public BSTNode(int key) {this.key = key;}public BSTNode(int key, Object value) {this.key = key;this.value = value;}public BSTNode(int key, Object value, BSTNode left, BSTNode right) {this.key = key;this.value = value;this.left = left;this.right = right;}}

查找关键词对应的值:

非递归

 public Object get(int key){BSTNode node=root;while(node!=null){if(key<node.key){node=node.left;}else if(key>node.key){node=node.right;}else{return node.value;}}return null;}

递归:

public Object get(int key){return doGet(root,key);}private Object doGet(BSTNode node, int key) {if (node == null) {return null;//没找到}if (key < node.key) {return doGet(node.left, key);//向左找} else if (key > node.key) {return doGet(node.right, key);}else  {return node.value;}}

查找最小关键词对应的值:

由于搜索二叉树的定义可知,左子树的值比根节点小,所以找到左子树中对应的最小关键词即可。

方法一:

 public Object min() {if (root == null) {return null;}BSTNode node = root;while (node.left != null) {node = node.left;}return node.value;}

方法二:

public Object min() {return doMin(root);}public Object doMin(BSTNode node){if(node==null){return null;}if(node.left==null){return node.value;}return doMin(node.left);}

查找最大关键词对应的值:

由于搜索二叉树的定义可知,右子树的值比根节点大,所以找到右子树中对应的最大关键词即可。

方法一:

public Object max(){return doMax(root);}public Object doMax(BSTNode node){if(node==null){return null;}if(node.right==null){return node.value;}return doMax(node.right);}

方法二:

public Object max(){BSTNode node=root;while(node.right!=null){node=node.right;}return node.value;}

存贮关键词对应的值:

在二叉树中能到的,进行覆盖;找不到的,进行插入

public void put(int key, Object value){BSTNode node=root;BSTNode parent = null;while(node!=null){parent=node;if(key<node.key){node=node.left;}else if(key>node.key){node=node.right;}else{//更新node.value=value;System.out.println("Updated key: " + key + ", value: " + value);return;}}//没有 插入//1.根节点if(parent==null){root=new BSTNode(key,value);System.out.println("Inserted root key: " + key + ", value: " + value);return;}//2.新节点key小于父节点的keyif(key<parent.key){parent.left=new BSTNode(key,value);System.out.println("Inserted left child of key: " + parent.key + ", key: " + key + ", value: " + value);} if(key>parent.key){//3.新节点key大于父节点的keyparent.right=new BSTNode(key,value);System.out.println("Inserted right child of key: " + parent.key + ", key: " + key + ", value: " + value);}}

查找关键词的前驱值:

不是中的紧挨的那种前驱值,而是key的前驱,5的前驱是4之类的

       4/  \2        7/\       /  \
1    3   6     8/5
 找到的情况:
情况1.节点有左子树,此时前任是左子树的最大值  4的前驱是3
情况2.节点没有左子树,若离他最近的,自左而来的祖先是前任 ,自左而来的会执行p=p.right;ch
public Object successor(int key){BSTNode p=root;BSTNode ancestorFromLeft=null;while(p!=null){if(key<p.key){p=p.left;}else if(key>p.key){//向右找意味着自左而来ancestorFromLeft=p;p=p.right;}else{break;}}//没找都if(p==null){return null;}//找到了//情况1.节点有左子树,此时前任是左子树的最大值 4的前驱是3if(p.left!=null){return doMax(p.left);  //找左子树的最大值}//情况2.节点没有左子树,若离他最近的,自左而来的祖先是前任return ancestorFromLeft!=null?ancestorFromLeft.value:null;}

查找关键词对应的后继值: 

 public Object predecessor(int key){BSTNode p=root;BSTNode ancestorFromRight=null;while(p!=null){if(key<p.key){ancestorFromRight = p;p=p.left;}else if(key>p.key){p=p.right;}else{break;}}if(p==null){return null;}//找到了//情况1.节点有右子树,此时后任是右子树的最小值//4的后任是5if(p.right!=null){return doMin(p.right);}//情况2.节点没有右子树,若离他最近的,自右而来的祖先是后任return ancestorFromRight!=null?ancestorFromRight.value:null;}

删除节点:

* 1.删除节点没有左孩子,将右孩子托给parent
* 2.删除节点没有右孩子,将左孩子托给parent
*3.删除节点没有左右孩子,已经被覆盖在1中,情况2中,把null托给parent
* 4.删除节点有左右孩子,可以把他的后继节点(s)托给parent(sp)
*       1. sp就是被删除节点,此时d与s紧绷,只需要将s托付给parent
*       2.s不是被删除节点,此时d与s不相邻,此时需要将s的后代托给s,再将s托给parent*

非递归:

public void delete(int key){BSTNode p=root;BSTNode parent=null;//1.找到被删除节点while(p!=null){if(key<p.key){parent=p;p=p.left;}else if(key>p.key){parent=p;p=p.right;}else{break;}}if(p.left==null){//情况1shift(parent,p,p.right);}else if(p.right==null){//情况2shift(parent,p,p.left);}else{//情况4  能进到这,说明有左右字数//4.1 找到后继节点   后继节点要遵循二叉搜索的规则,左子树小,右子树大BSTNode s=p.right;BSTNode sParent=p;//后继父亲//找最小值while(s.left!=null){sParent=s;s=s.left;}if(sParent!=p){//4.2 删除节点与后继不相邻,处理后继的后事shift(sParent,s,s.right);//不可能有左孩子,因为要找到后继的最小值s.right=p.right;}//4.3 将后继托给被删除节点shift(parent,p,s);s.left=p.left;}}//托孤private void shift(BSTNode parent,BSTNode delete,BSTNode child){if(parent==null){root=child;}else if(delete==parent.left){parent.left=child;}else {parent.right=child;}}

递归:

public Object delete(int key){ArrayList<Object> result=new ArrayList<>();//被删除节点的值root=doDelete(root,key,result);return result.isEmpty() ? null : result.get(0);}//返回剩下的孩子private BSTNode doDelete(BSTNode node, int key, ArrayList<Object> result){//起点,要删除的keyif(node==null){return null;}if(key<node.key){node.left=doDelete(node.left,key, result);return node;}if(key>node.key){node.right=doDelete(node.right,key, result);return node;}//找到了result.add(node.value);//情况1没有左孩子if(node.left==null){return node.right;}//情况2没有右孩子if(node.right==null){return node.left;}//情况3有左右孩子//1.相邻的BSTNode s=node.right;while(s.left!=null){s=s.left;}s.right=doDelete(node.right,s.key, new ArrayList<>());//起点,要删除的key  这个值不需要存入s.left=node.left;return s;}

范围

1.小于某值的范围

 public List<Object> less(int key){ArrayList<Object> result=new ArrayList<>();LinkedList<BSTNode> stack=new LinkedList<>();BSTNode p=root;while(p!=null||!stack.isEmpty()){if(p!=null){stack.push(p);p=p.left;}else {BSTNode pop=stack.pop();if(pop.key<key){result.add(pop.value);}else{break;}p=pop.right;}}return result;}

2.大于某值的范围

 public List<Object> greater(int key){ArrayList<Object> result=new ArrayList<>();LinkedList<BSTNode> stack=new LinkedList<>();BSTNode p=root;while(p!=null||!stack.isEmpty()){if(p!=null){stack.push(p);p=p.right;//先往右找的}else {BSTNode pop=stack.pop();if(pop.key>key){result.add(pop.value);}else{break;}p=pop.left;}}return result;}

3.在区间的值

 public List<Object> between(int min,int max){ArrayList<Object> result=new ArrayList<>();LinkedList<BSTNode> stack=new LinkedList<>();BSTNode p=root;while(p!=null||!stack.isEmpty()){if(p!=null){stack.push(p);p=p.left;}else {BSTNode pop=stack.pop();if(pop.key>=min&&pop.key<=max){result.add(pop.value);}else if(pop.key>max){  //这个是重要的结束条件break;}p=pop.right;}}return result;}

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

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

相关文章

python爬虫-爬虫常用函数及其用法-1

1、urllib库 urllib库是python中一个最基本的网络请求库。可以模拟浏览器的行为&#xff0c;向指定的服务器发送一个请求&#xff0c;并可以保存服务器返回的数据。 &#xff08;1&#xff09;urlopen函数 在 python3 的 urllib 库中&#xff0c;所有和网络请求相关的方法&a…

vue3 路由守卫

在Vue 3中&#xff0c;路由守卫是一种控制和管理路由跳转的机制。它允许你在执行导航前后进行一些逻辑处理&#xff0c;比如权限验证、数据预取等&#xff0c;从而增强应用的安全性和效率。路由守卫分为几种不同的类型&#xff0c;每种类型的守卫都有其特定的应用场景。 其实路…

web——sqliabs靶场——第八关——sqlmap的使用

第八关还是用到了盲注&#xff0c;我们来使用kali里的sqlmap工具来搞一下。 1.sqlmap简介 sqlmap 是一款开源的自动化 SQL 注入和数据库接管工具&#xff0c;旨在帮助安全研究人员和渗透测试人员检测和利用 SQL 注入漏洞。它支持多种数据库管理系统&#xff08;如 MySQL、Post…

如何去掉el-input 中 type=“number“两侧的上下按键

<el-input v-model.trim"row.length" type"number" min"0" placeholder""></el-input> // 如何去掉el-input-number两侧的上下按键 ::v-deep input::-webkit-outer-spin-button, ::v-deep input::-webkit-inner-spin-butt…

【Redis】redis缓存击穿,缓存雪崩,缓存穿透

一、什么是缓存&#xff1f; 缓存就是与数据交互中的缓冲区&#xff0c;它一般存储在内存中且读写效率高&#xff0c;提高响应时间提高并发性能&#xff0c;如果访问数据的话可以先访问缓存&#xff0c;避免数据查询直接操作数据库&#xff0c;造成后端压力过大。 但是可能会面…

统⼀数据返回格式快速⼊⻔

为什么会有统⼀数据返回&#xff1f; 其实统一数据返回是运用了AOP&#xff08;对某一类事情的集中处理&#xff09;的思维。 优点&#xff1a; 1.⽅便前端程序员更好的接收和解析后端数据接⼝返回的数据。 2.降低前端程序员和后端程序员的沟通成本&#xff0c;因为所有接⼝都…

第7章硬件测试-7.6 量产可靠性测试

7.6 量产可靠性测试 7.6.1 生产小批量测试7.6.2 装备测试7.6.3 器件一致性测试7.6.4 工艺规程和单板维修技术说明 产品量产阶段需要通过可靠性测试来保障产品的可靠性。 7.6.1 生产小批量测试 生产小批量测试是发货之前的批量压力测试&#xff0c;有两个目的&#xff1a;一是…

可编辑的 SALV 模型(克服 SALV 模型的限制)

我们都知道 ABAP Object 比传统的 ABAP 非常强大。在这里&#xff0c;我想分享我使用 ABAP 对象克服 SALV mdoel 限制的最佳实验之一。 起源 最初&#xff0c;我在 SCN 上发布了这篇文章 – ABAP 对象的强大功能&#xff1a;克服 SALV 模型的限制&#xff0c;它也受到了很多批…

通过shell脚本分析部署nginx网络服务(详细易懂)

通过shell脚本分析部署nginx网络服务 要求&#xff1a; 接收用户部署的服务名称判断服务是否安装 已安装&#xff1b;自定义网站配置路径为/www&#xff1b;并创建共享目录和网页文件&#xff1b;重启服务 没有安装&#xff1b;安装对应的软件包测试&#xff1a; 判断服务是否…

H.265流媒体播放器EasyPlayer.js H5流媒体播放器如何验证视频播放是否走硬解

随着技术的不断进步和5G网络的推广&#xff0c;中国流媒体播放器行业市场规模以及未来发展趋势都将持续保持稳定的增长&#xff0c;并将在未来几年迎来新的发展机遇。流媒体播放器将继续作为连接内容创作者和观众的重要桥梁&#xff0c;推动数字媒体产业的创新和发展。 EasyPla…

【 LVGL】用外部FLASH存储字库并显示

LVGL–用外部FLASH存储字库并显示 应用场景 由于使用的芯片内部FLASH空间有限&#xff0c;如果仅使用英文字库并用不了多少空间&#xff0c;但是项目需要支持中英文字库&#xff0c;中文字库添加2w字左右&#xff0c;10px大小就要1M多了&#xff0c;内部空间根本不够用&#…

含284个数据集,覆盖18项临床任务,上海AI Lab等发布多模态医疗基准GMAI-MMBench

「有这样一台智能医疗设备&#xff0c;患者只需躺在智能医疗设备上便可完成从扫描、诊断、治疗、修复的全过程&#xff0c;实现健康的重启」。这是 2013 年上映的科幻电影「极乐空间」中的一个情节。 电影《极乐空间》场景 如今&#xff0c;随着人工智能技术的飞速发展&#xf…

Java-04

目录 Redis如何实现延时队列 延时队列的组成 生产消息 消费消息 实现细节 Redis集群 Integer.compare(a[1], b[1]))与a[1] - b[1]) 设计模式​编辑 算法 Redis如何实现延时队列 使用 sortedset &#xff0c;拿时间戳作为 score &#xff0c;消息内容作为 key 调用 zad…

【C++】— 掌握STL vector 类:“Vector简介:动态数组的高效应用”

文章目录 1.vector的介绍和使用1.1vector的介绍1.2 vector的特点1.3vector的使用1.3.1vector的定义1.3.2vector iterator的使用1.3.3vector 的空间增长问题1.3.4 vector 的增删查改1.3.5vector 迭代器失效问题 1.vector的介绍和使用 1.1vector的介绍 vector是一个顺序容器&am…

CSS3中的伸缩盒模型(弹性盒子、弹性布局)之伸缩容器、伸缩项目、主轴方向、主轴换行方式、复合属性flex-flow

简介&#xff1a; 1.伸缩盒模型简介 2.伸缩容器、伸缩项目 3-4.主轴方向 5.主轴换行方式 6.复合属性flex-flow 7.主轴的对齐方式

互联网数字化商品管理浪潮思考:从信息化到精准运营

目录 一、商品数字化转型面临的现状分析 &#xff08;一&#xff09;运营方向分析 &#xff08;二&#xff09;商品归类分析 二、商品数字化管理建设分析 三、基础建设——商品信息数字化 &#xff08;一&#xff09;商品信息质量数字化的目的 &#xff08;二&#xff0…

STL关联式容器之RB-tree(红黑树)

AVL-tree之外&#xff0c;另一个颇具历史并被广泛运用的平衡二叉搜索树是RB-tree&#xff08;红黑树&#xff09;。所谓RB-tree&#xff0c;不仅是一颗二叉搜索树&#xff0c;而且必须满足一下规则&#xff1a; 1&#xff1a;每个节点不是红色就是黑色 2&#xff1a;根节点为…

电脑系统重装小白教程

​对于很多电脑用户来说&#xff0c;系统出现故障或者需要清理时&#xff0c;重装系统是一项不可避免的操作。但是&#xff0c;对于没有技术基础的小白用户而言&#xff0c;重装系统可能会显得复杂且困难。本文将为您提供一份简洁易懂的电脑系统重装教程&#xff0c;帮助您顺利…

使用Ollama和Open WebUI管理本地开源大模型

Open WebUI和Ollama介绍 Open WebUI 是一个功能丰富且用户友好的自托管 Web 用户界面&#xff08;WebUI&#xff09;&#xff0c;它被设计用于与大型语言模型&#xff08;LLMs&#xff09;进行交互&#xff0c;特别是那些由 Ollama 或与 OpenAI API 兼容的服务所支持的模型。O…

Nmap识别MongoDB 6.0指纹

Nmap识别MongoDB 6.0指纹 朋友反馈一个问题&#xff0c;说使用Nmap扫描MongoDB服务时对于6.0以上的版本默认无法识别到服务版本信息。 如上图所示&#xff0c;对应的VERSION信息是空的&#xff0c;在提示信息中可以看到&#xff0c;官方推荐将指纹信息上传以帮助更新服务指纹&…