引言:

上次我们结束了类和对象的收尾,之后我们就要学习一些高级的数据结构,今天我们先来看一个数据结构-- 二叉搜索树。

一: 二叉搜索树的概念(性质)

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

  1. 若它的左子树不为空,则左子树上所有结点的值都小于等于根结点的值。
  2. 若它的右子树不为空,则右子树上所有结点的值都大于等于根结点的值。
  3. 它的左右子树也分别为二叉搜索树
  4. 二叉搜索树中可以支持插入相等的值,也可以不支持插入相等的值,具体看使用场景定义,后续我们学习map/set/multimap/multiset系列容器底层就是二叉搜索树,其中map/set不支持插入相等值,multimap/multiset支持插入相等值。

左图就是map不支持插入相同的数据。
右图就是multimap支持插入相同的数据。
在这里插入图片描述

二:二叉搜索树的性能分析:

最优情况下,二叉搜索树完全二叉树(或者接近完全二叉树),其高度为: log2N
最差情况下,二叉搜索树退化为单支树(或者类似单支),其高度为:N
所以综合而言二叉搜索树增删查改时间复杂度为:O(N)
在这里插入图片描述
那么这样的效率显然是无法满足我们需求的,我们后续会接着学习二叉搜索树的变形,平衡二叉搜索树AVL树)和红黑树,才能适用于我们在内存中存储和搜索数据。
另外需要说明的是,二分查找也可以实现o(log2N)级别的查找效率,但是二分查找有两大缺陷:

  1. 需要存储在支持下标随机访问的结构中,并且有序
  2. 插入和删除数据效率很低,因为存储在下标随机访问的结构中,插入和删除数据一般需要挪动数据
    因此这里也就体现出了平衡二叉搜索树的价值。

三:模拟实现二叉搜索树

1. 基本框架:

因为二叉搜索树二叉树衍生而来的,因此其基本结构和二叉树差不多,因此这里我们就不细讲:
在这里插入图片描述

2. 插入数据:

(1)插入原则:

插入的具体过程如下:

  1. 树为空,则直接新增结点,赋值给root指针。
  2. 树不空,按二叉搜索树性质,插入值比当前结点大往右走,插入值比当前结点小往左走,找到空位置,插入新结点。
  3. 如果支持插入相等的值,插入值跟当前结点相等的值可以往右走,也可以往左走,找到空位置,插入新结点。(要注意的是要保持逻辑一致性,插入相等的值不要一会往右走,一会往左走,但是这里我们实现的是不支持插入相同数据的)
(2)思路分析:

在这里插入图片描述

(3)补充:在这里插入图片描述

注:由于插入数据的时候牵扯到数据的申请,因此这里的节点结构要提供对于的构造函数来生成节点。

(4)代码实现:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(5)测试:

注:这里为了测试插入数据,因此我们再实现一个中序遍历。

中序遍历实现:

在这里插入图片描述
在这里插入图片描述
可以看到测试结果没有问题。

3. 查找数据:

(1)查找原则:

从根开始比较,查找x,x比根的值大则往右边走查找,x比根值小则往左边走查找。
2. 最多查找高度次,走到空,还没找到,这个值不存在。
3. 如果不支持插入相等的值,找到x即可返回。
4. 如果支持插入相等的值,意味着有多个x存在,一般要求查找中序的第一个x。如下图,查找3,要找到1的右孩子的那个3返回。

在这里插入图片描述

(2)思路分析:

查找的逻辑和插入的逻辑基本上一样,就不再具体分析。

(3) 代码实现:

在这里插入图片描述

(4)测试:

在这里插入图片描述
测试没问题。

4. 删除数据:

相较于插入数据,删除数据就比较复杂了,需要考虑各种情况,下面我们来一点点分析:
首先查找元素是否在二叉搜索树中,如果不存在,则返回false
如果查找元素存在则分以下四种情况分别处理:(假设要删除的结点为N)

  1. 要删除结点N左右孩子均为空。
  2. 要删除的结点N左孩子位空,右孩子结点不为空。
  3. 要删除的结点N右孩子位空,左孩子结点不为空。
  4. 要删除的结点N左右孩子结点均不为空。
    对应以上四种情况的解决方案:
  5. 把N结点的父亲对应孩子指针指向空,直接删除N结点(情况1可以当成2或者3处理,效果是一样的)
  6. 把N结点的父亲对应孩子指针指向N的右孩子,直接删除N结点。
  7. 把N结点的父亲对应孩子指针指向N的左孩子,直接删除N结点。
  8. 无法直接删除N结点,因为N的两个孩子无处安放,只能用替换法删除。找N左子树的值最大结点R(最右结点)或者N右子树的值最小结点R(最左结点)替代N,因为这两个结点中任意一个,放到N的位置,都满足二叉搜索树的规则。替代N的意思就是N和R的两个结点的值交换,转而变成删除R结点,R结点符合情况2或情况3,可以直接删除。
(1) 思路分析:

在这里插入图片描述
在这里插入图片描述

(2)代码实现:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述在这里插入图片描述

(3) 测试:

在这里插入图片描述

5. 销毁

(1)思路分析:

跟之前我们的二叉树销毁一样,只需要后序遍历来销毁即可。

(2) 代码实现:

在这里插入图片描述

6. 拷贝构造函数

这里跟之前二叉树的构建一样,只需要一边遍历一边构建即可。

(2)代码实现:

在这里插入图片描述
在这里插入图片描述

(3)测试:

在这里插入图片描述

7. 赋值运算符重载:

(1)思路分析:

这里的赋值运算符重载和之前差不多,还是复用拷贝构造函数。

(2)代码实现:

在这里插入图片描述

(3)测试:

在这里插入图片描述

完结!!!

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

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

相关文章

【Redis】Sentinel哨兵

🛡️ 深入理解 Redis Sentinel:高可用架构的守护者 在实际开发中,我们常用 Redis 构建缓存系统或数据中间件。然而,主从复制虽然能实现数据同步,但无法自动故障转移(failover),这就…

Shell脚本应用及实战演练

文章目录 一、Shell脚本语言的基本结构1、Shell脚本的用途:2、 Shell脚本基本结构:3、 创建Shell脚本过程4、 脚本注释规范 二、Shell脚本语言的变量用法详解位置与预定义变量 三、 Shell字符串详解1、Shell字符串拼接2、Shell字符串截取3、 Shell的格式…

软件工程瀑布模型学习指南

软件工程瀑布模型学习指南 一、瀑布模型核心概念 1.1 定义与特点 瀑布模型是一种经典的软件开发流程,将项目划分为顺序性的阶段,每个阶段有明确的输入和输出,如同瀑布流水般单向推进。其特点包括: 阶段间具有明确的顺序性和依赖性强调文档驱动和阶段评审适合需求明确、稳…

获取gitlab上项目分支版本(二)

获取gitlab上项目分支版本_gitlab代码分支版本在哪-CSDN博客 原先写过一版,但是这次想更新一下项目的分支信息时,提示我 git服务器上的Python版本是2.7.3,这个错误表明当前Python环境中没有安装requests库,服务器也没有连接外网&…

主流防火墙策略绕过漏洞的修复方案与加固实践

主流防火墙策略绕过漏洞的修复方案与加固实践 流量关键点分析(攻击手法) 攻击者通过精心构造的TCP序列号攻击和恶意标志组合绕过防火墙DPI检测,核心手法如下: TCP连接建立(正常握手) 1049:客户…

泛微OAe9-后端二开常见数据库操作

泛微OAe9-后端二开常见数据库操作 文章目录 泛微OAe9-后端二开常见数据库操作一、RecordSet1 RecordSet 操作OA本身的表2 RecordSet 操作OA 本身的存储过程 二、RecordSetTrans三、RecordSetDataSource四、原生 jdbc 一、RecordSet RecordSet 适用于操作 OA 自己的库。OA 数据库…

【数据分析八:hypothesis testing】假设检验

本节我们讲述假设检验和抽样方法 有关假设检验的详细内容,可以参考我以往的博客 概率论与数理统计总复习_概率论与数理统计复习-CSDN博客文章浏览阅读1.5k次,点赞33次,收藏23次。中科大使用的教辅《概率论和数理统计》,带大家复…

AI免费工具:promptpilot、今天学点啥、中英文翻译

promptpilot 激发模型潜能,轻松优化 Prompt https://promptpilot.volcengine.com/startup 今天学点啥 https://metaso.cn/study 能生成网页和语音播报 中英文翻译 沉浸式翻译,浏览器插件,ai翻译

计算机网络学习笔记:TCP三报文握手、四报文挥手

文章目录 前言一、TCP三报文握手二、TCP四报文挥手三、TCP保活计时器 前言 TCP通信,通常需要经历三个阶段:三报文握手->发送,接收数据->四报文挥手。 一、TCP三报文握手 三报文握手处于TCP的连接建立阶段,主要解决了以下的…

kafka部署和基本操作

一、部署kafka 解压 tar xzvf kafka_2.12-3.9.1.tgz tar -zxf kafka_2.12-3.9.1.tgz 1.修改config/server.properties # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # …

Bootstrap 5学习教程,从入门到精通,Bootstrap 5 导航语法知识点及案例代码(17)

Bootstrap 5 导航语法知识点及案例代码 Bootstrap 5 提供了强大的导航组件,帮助开发者快速构建响应式且美观的导航栏。 一、Bootstrap 5 导航组件概述 Bootstrap 5 提供了多种导航组件,主要包括: 导航栏(Navbar)&am…

清除 docker 无用的 镜像/容器

清除 docker 无用的 镜像/容器 删除 <none> 的 docker 镜像 使用以下命令删除所有 的 Docker 镜像&#xff08;即悬空镜像 / dangling images&#xff09;&#xff1a; docker image prune -f这会自动删除所有没有 tag 的镜像&#xff08;&#xff09;&#xff0c;不会…

使用Charles抓包工具提升API调试与性能优化效率

在软件开发过程中&#xff0c;网络请求调试和性能优化往往成为开发者遇到的挑战&#xff0c;尤其是在进行API接口调试时。开发者需要确保网络请求的正确性、响应时间以及系统的整体性能。然而&#xff0c;传统的调试方法常常无法提供足够的细节来深入分析问题&#xff0c;进而影…

如何协调各项目关键节点的冲突与依赖

在多项目并行的环境下&#xff0c;关键节点间的冲突与依赖是导致项目延期、资源浪费和沟通误解的主要根源。要高效协调此类问题&#xff0c;企业应重点从建立透明的进度依赖图、使用项目管理工具对齐节点、推动跨部门协同机制入手。其中&#xff0c;通过Gantt图或关键路径法实现…

mongodb单节点改副本集模式

前一阵将三节点的副本集改成了单节点&#xff0c;但后面业务代码出现问题&#xff1a;无法使用事务&#xff0c;因为事务只有在副本集上能用&#xff0c;单节点无法使用&#xff0c;故需要改回副本集模式&#xff0c;而我目前仅有一台服务器&#xff0c;所以考虑在一台服务器上…

Android 修改了页面的xml布局,使用了databinding,这时候编译时需要用到apt吗

deepseek回答&#xff1a; 在 Android 开发中使用 DataBinding 时&#xff0c;不需要显式使用 apt&#xff08;Annotation Processing Tool&#xff09;。以下是详细说明&#xff1a; 1. DataBinding 的编译机制 DataBinding 是 Android Gradle 插件原生支持的功能&#xff…

服务器如何从http升级到https(nginx)

1.证书申请 可以到阿里云或者华为云去申请证书&#xff0c;申请完下载证书是个压缩包&#xff0c;然后解压 可以到到几个文件夹&#xff0c;找到 .Nginx 文件夹打开 会有两个文件&#xff0c;将这两个文件上传至nginx/conf/cert文件夹下&#xff08;cert需要手…

6.19_JAVA_微服务

1、跑后端的时候要把数据库跑起来&#xff0c;否则会报错。 2、predicate断言&#xff1a; 预言&#xff1a;predict 3、gateway&#xff1a;出路口 4、API&#xff1a;List.of("a", "b", "c");把abc编程一个集合。 5、 6、shortcutFieldOrd…

Linux 基础命令:`ls`、`cd`、`du` 快速入门

在 Linux 系统中&#xff0c;ls、cd 和 du 是日常操作中最常用的三个命令。掌握它们能大幅提升文件管理效率。 1. ls&#xff1a;查看目录内容 用途&#xff1a;列出当前或指定目录下的文件和子目录。 常用命令&#xff1a; ls -l # 详细列表&#xff08;权限、大…

408第一季 - 数据结构 - 散列表

散列表 概念 散列表本身就是为了查找 原始人思想 散列表思想 6%5 是 1 1%5 也是1 冲突 冲突怎么办&#xff1f; 线性探测法 就往后找&#xff0c;1跑到索引为2 然后查找&#xff0c;可以发现&#xff0c;只要没冲突就只用查找1次 然后你想找10的话&#xff0c;发现索引为0…