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

【C++】二叉搜索树Binary Search Tree

Binary Search Tree

  • 二叉搜索树的概念
  • 二叉搜索树的操作
  • 二叉搜索树的实现
    • 查找
    • 插入
    • 删除
  • 二叉搜索树的应用
  • 二叉搜索树的性能分析

二叉搜索树的概念

二叉搜索树又被称为二叉排序树,顾名思义,当我们使用中序遍历时,会得到一个有序的序列。二叉搜索树有如下的性质:
1.若它的左子树不为空,则左子树上每个节点的值都小于根节点的值。
2.若它的右子树不为空,则右子树上每个节点的值都大于根节点的值。
3.左右子树也是二叉搜索树
在这里插入图片描述
如图所示,就是一颗二叉搜索树。它的中序遍历结果为:1,3,4,6,7,8,10,13,14

二叉搜索树的操作

二叉搜索树的操作有:查找,插入,删除。
查找
1.从根开始比较,查找,比根大则往右边走查找,比根小则往左边走查找
2.最多查找高度次,走到到空,还没找到,这个值不存在

插入
分为树是否为空:
若为空树:树为空,则直接新增节点,赋值给root指针
若不为空树:按二叉搜索树性质查找插入位置,插入新节点

删除

首先要查找要删除的节点是否在二叉树中,若不存在,则直接返回,若存在,分情况进行删除。
a.要删除的节点没有孩子
b.要删除的节点只有左孩子
c.要删除的节点只有右孩子
d.要删除的节点左右孩子都有

实际上,对于删除操作来说,可以要删除没有孩子节点或删除只有一个孩子节点的情况,操作是相同的,都是直接将要删除的节点的双亲节点的指针指向当前删除节点的孩子节点。(当前节点如果没有孩子节点,实际上当前节点的孩子节点是nullptr,当前节点有孩子节点,实际上也是将双亲指向当前的孩子节点)

因此,可以将四种情况中a和b情况进行合并,那么就只有三种情况了。
a.要删除的节点没有孩子或者只有右孩子-------将双亲节点指向当前节点的右孩子,然后直接删除当前节点
b.要删除的节点只有左孩子-------将双亲节点指向当前节点的左孩子,然后直接删除当前节点
c.要删除的节点左右孩子都有------在它的右子树下找到最小的一个节点(右子树的最左侧),用它的值填补到被删除节点中,再处理该节点的删除问题

二叉搜索树的实现

查找

1.从根开始比较,查找,比根大则往右边走查找,比根小则往左边走查找
2.最多查找高度次,走到到空,还没找到,这个值不存在

Node* Find(const T& data){Node* cur = _root;while (cur){if (data > cur->_data){cur = cur->_right;}else if (data < cur->_data){cur = cur->_left;}elsereturn cur;}return nullptr;}

插入

分为树是否为空:
若为空树:树为空,则直接新增节点,赋值给root指针
若不为空树:按二叉搜索树性质查找插入位置,插入新节点

bool Insert(const T& data){//空树,插入成功后就是根节点if (_root == nullptr){_root = new Node(data);return true;}//非空就需要找到待插入的位置。Node* cur = _root;Node* parent = nullptr;while (cur){parent = cur;if (cur->_data > data)cur = cur->_left;else if (cur->_data < data)cur = cur->_right;elsereturn false;} cur = new Node(data);if (cur->_data > parent->_data){parent->_right = cur;}elseparent->_left = cur;return true;}

删除

首先要查找要删除的节点是否在二叉树中,若不存在,则直接返回,若存在,分情况进行删除。
a.要删除的节点没有孩子
b.要删除的节点只有左孩子
c.要删除的节点只有右孩子
d.要删除的节点左右孩子都有

实际上,对于删除操作来说,可以要删除没有孩子节点或删除只有一个孩子节点的情况,操作是相同的,都是直接将要删除的节点的双亲节点的指针指向当前删除节点的孩子节点。(当前节点如果没有孩子节点,实际上当前节点的孩子节点是nullptr,当前节点有孩子节点,实际上也是将双亲指向当前的孩子节点)

因此,可以将四种情况中a和b情况进行合并,那么就只有三种情况了。
a.要删除的节点没有孩子或者只有右孩子-------将双亲节点指向当前节点的右孩子,然后直接删除当前节点
b.要删除的节点只有左孩子-------将双亲节点指向当前节点的左孩子,然后直接删除当前节点
c.要删除的节点左右孩子都有------在它的右子树下找到最小的一个节点(右子树的最左侧),用它的值填补到被删除节点中,再处理该节点的删除问题

最终我们可以将情况分为上述的a b c三种情况,

对于情况a来说,其内部又可以分为两大类:要删除的是根节点要删除的不是根节点
对于情况b来说,其内部又可以分为两大类:要删除的是根节点要删除的不是根节点
对于情况c来说,我们是通过步骤:1.在待删除节点的右子树中找到最小的节点(替代节点) 2.将替代节点的值赋给待删除的节点 3.删除找到的替代节点.

而在a情况中,针对要删除的节点不是根节点,我们需要判断待删除的节点是其双亲节点的左孩子还是右孩子。因为到时候需要让双亲节点指向待删除节点的左孩子
而在b情况中,针对要删除的节点不是根节点,我们需要判断待删除的节点是其双亲节点的左孩子还是右孩子。因为到时候需要让双亲节点指向待删除节点的右孩子
而在c情况中,我们需要判断替代节点的是其双亲的左孩子还是右孩子。因为到时候需要让双亲节点指向待删除节点的右孩子

下图是上述分类情况的图示。

只有右孩子的场景
在这里插入图片描述
只有左孩子的场景
在这里插入图片描述

左右孩子均存在的场景
在这里插入图片描述
这个是对于删除操作需要分的情况:
在这里插入图片描述

针对上述分的情况,代码的实现

bool Erase(const T& data){//找待删除节点的位置,并且保存双亲Node* cur = _root;Node* parent = nullptr;while (cur){parent = cur ;if (data == cur->_data)break;else if (data < cur->_data){parent = cur;cur = cur->_left;}else{parent = cur;cur = cur->_right;}}//值在BST中不存在值为data的节点if (cur == nullptr)return false;// 只有右孩子或者没有孩子if (cur->_left == nullptr){// 1.双亲为空,说明为根节点if (parent == nullptr)_root = cur->_right;// 2.双亲非空,说明不是根节点else{//可能是双亲的左孩子if (cur = parent->_left)parent->_left = cur->_right;//也可能是双亲的右孩子elseparent->_right = cur->_right;}delete cur;}//只有左孩子else if (cur->_right == nullptr){// 1.双亲为空,是根节点if (parent == nullptr)_root = cur->_left;// 2.双亲不为空,不是根节点else{if (cur == parent->_left)parent->_left = cur->_left;elseparent->_right = cur->_left;}delete cur;}//左右孩子均存在,//先在其右子树中找到最左边的节点,//将替代节点中的值赋给要删除的节点,//删除替代节点else{Node* tmp = cur->_right;parent = cur;//在cur的右子树中找替代节点while (tmp->_left){parent = tmp;tmp = tmp->_left;}//用替代节点中的值替换待删除的节点cur->_data = tmp->_data;//删除替代节点if (parent->_left == tmp)parent->_left = tmp->_right;elseparent->_right = tmp->_right;delete tmp;}return true;

二叉搜索树的应用

k模型和kv模型

k模型是指:只有key作为关键码,结构中只需要存储Key即可,关键码即为需要搜索到的值。
例如:要查找一个单词是否拼写正确,我们可以先将所有的单词作为key构建一个二叉搜索树。在这个二叉搜索树中去查找是否有我们想找到的单词,若可以找到,则证明拼写正确,若找不到,则证明拼写错误。

kv模型是指:每一个关键码key,都有与之对应的值Value,即<Key, Value>的键值对。
例如:英汉词典是一个典型的kv模型,通过英文可以快速找到与其对应的中文。英文和中文就构成了一对键值对

二叉搜索树的性能分析

因为对应二叉搜索树来说,插入和删除操作都要先进行查找,查找的效率高低直接决定了各个操作的性能。

对有n个结点的二叉搜索树,若每个元素查找的概率相等,则二叉搜索树平均查找长度是结点在二叉搜索树的深度的函数,即结点越深,则比较次数越多。

但对于同一个关键码集合,如果各关键码插入的次序不同,可能得到不同结构的二叉搜索树:
在这里插入图片描述
如果关键码集合,插入的次序接近于无序,则会构造出作图这样的二叉搜索树,而插入的次序如果是有序的,则会构造出右图这样的单支树。

而不同的二叉搜索树,其比较的平均次数是不同的。
最优情况下:二叉搜索树为完全二叉树(或者接近完全二叉树),其平均比较次数为:O(logN)(以2为底)
最差情况下,二叉搜索树退化为单支树(或者类似单支),其平均比较次数为:O(N)(以2为底)

正是由于插入的次序不同,会导致构造的二叉搜索树的结构不同,而退化成单枝时,二叉搜索树就失去了优势,因此如果需要按照任意次序插入时,都能让二叉搜索树的性能达到最优,就需要用到AVL树和红黑树了。

相关文章:

【C++】二叉搜索树Binary Search Tree

Binary Search Tree 二叉搜索树的概念二叉搜索树的操作二叉搜索树的实现查找插入删除 二叉搜索树的应用二叉搜索树的性能分析 二叉搜索树的概念 二叉搜索树又被称为二叉排序树&#xff0c;顾名思义&#xff0c;当我们使用中序遍历时&#xff0c;会得到一个有序的序列。二叉搜索…...

Hover.css动画库的使用

目录 1、 Hover.css是什么&#xff1f; 2、引入 2.1、整个文件引入 2.2、复制所需要的代码 案例&#xff1a; 1. 卷边效果 2. 调整大小的卷边 类别&#xff1a; 1、 Hover.css是什么&#xff1f; Hover.css是一个CSS3鼠标悬停的动画方案&#xff0c;里面包含了许多纯c…...

Baumer工业相机堡盟工业相机如何通过文件保存和导入的方式保存和载入相机的各类参数(C#)

Baumer工业相机堡盟工业相机如何通过文件保存和导入的方式使保存和载入相机的各类参数&#xff08;C#&#xff09; Baumer工业相机Baumer工业相机BGAPISDK中UserSet的技术背景相机配置文件代码案例分享第一步&#xff1a;保存相机当前参数设置doUserSetStore为文件第二步&#…...

封装设计!抽象BasePage,提升WEB自动化测试用例质量和效率

目录 前言&#xff1a; 一、什么是抽象BasePage 二、BasePage中的属性和方法 三、BasePage中的代码实现 四、抽象Page对象 五、测试用例 六、总结 前言&#xff1a; 对于测试工程师来说&#xff0c;WEB自动化测试是非常重要的一部分。然而&#xff0c;WEB自动化测试的开…...

c primer plus学习笔记(一)

1.int的大小恒定就是32位么&#xff1f; 不是的&#xff0c;int大小是跟着系统走的&#xff0c;不是在各个系统里固定不变的。 32位系统int就是32位。64位系统&#xff0c;int就是64位。short 和long的长度则跟着int走&#xff0c;一般来说int是32位&#xff0c;short就是16位…...

C语言2:说心里话

描述 分两次从控制台接收用户的两个输入&#xff1a;第一个内容为“人名”&#xff0c;第一个内容为“心里 话”。 然后将这两个输入内容组成如下句型并输出出来&#xff1a; 1.(人名&#xff09;&#xff0c;I want to say&#xff0c;(心里话 2. 输入输出示例: 输入&#xff…...

任务19 简单个人电话号码查询系统

系列文章 任务19 简单个人电话号码查询系统 问题描述 人们在日常生活中经常需要查找某个人或某个单位的电话号码&#xff0c;本实验将实现一个简单的个人电话号码查询系统&#xff0c;根据用户输入的信息&#xff08;例如姓名等&#xff09;进行快速查询。基本要求 (1) 在外存…...

day4--链表内指定区间反转

迭代方法 1. 第m个节点的前一个节点pre和第n个节点&#xff1b; 2. 将第m个节点到第n个节点的链表部分反转&#xff1b; 3. 将pre节点的next指向反转后链表的头节点&#xff0c;将反转后链表的尾节点的next指向n1节点。 /*** struct ListNode {* int val;* struct ListNode…...

HTTP状态码是什么?常用的状态码有什么?

HTTP&#xff08;Hypertext Transfer Protocol&#xff09;是一种用于传输超文本和其他内容的应用层协议。 历史&#xff1a; HTTP最早的版本是HTTP/0.9&#xff0c;它只支持简单的 GET 请求&#xff0c;而不支持其他操作。 HTTP/1.0 版本增加了许多新特性&#xff0c;如支持…...

【软件分析/静态分析】学习笔记01——Introduction

&#x1f517; 课程链接&#xff1a;李樾老师和谭天老师的&#xff1a;南京大学《软件分析》课程01&#xff08;Introduction&#xff09;_哔哩哔哩_bilibili 目录 一、静态程序分析介绍 1.1 PL and Static Analysis 程序语言和静态分析 1.2 为什么要学 Static Analysis? …...

Java数组

文章目录 前言一维数组数组定义创建数组数组的内存模型数组数据初始化数组元素访问遍历数组length常见数组异常 二分查找数组的操作数组的复制数组的排序 二维数组扩展 Java中定义数组的语法如下&#xff1a; 数据类型[] 数组名 new 数据类型[数组长度]; 数据类型指的是数组中…...

【数据库原理入门】

数据库原理&#xff1a;深入探索与实践指南 引言 在我们的日常生活中&#xff0c;数据库无处不在&#xff0c;从在线购物、银行交易到社交媒体&#xff0c;都离不开数据库。要想成为一名出色的开发者&#xff0c;理解数据库原理是非常重要的。本文将以简明易懂的方式&#xf…...

练习Vue烘培坊项目

烘培坊项目 文章目录 烘培坊项目项目概述项目页面展示后台管理页面登录页面文章详情页面稿件发布页面 项目关键代码实现后台管理页面稿件管理页面内容列表页面文章详情页面烘培坊主页面注册页面登录页面个人信息页面稿件发布页面 项目概述 烘培坊&#xff08;Bakery&#xff0…...

API测试| 了解API接口测试| API接口测试指南

什么是API&#xff1f; API是一个缩写&#xff0c;它代表了一个 pplication P AGC软件覆盖整个房间。API是用于构建软件应用程序的一组例程&#xff0c;协议和工具。API指定一个软件程序应如何与其他软件程序进行交互。 例行程序&#xff1a;执行特定任务的程序。例程也称为过…...

使用canvas给图片添加水印

上接文章“图片处理” canvas元素其实就是一个画布&#xff0c;我们可以很方便地绘制一些文字、线条、图形等&#xff0c;它也可以将一个img标签里渲染的图片画在画布上。 我们在上传文件到后端的时候&#xff0c;使用input标签读取用户本地文件后得到的其实是一个Blob对象&a…...

栈和队列的概念和实现

栈 栈 定义&#xff1a;只能在一端进行插入或删除操作的的线性表 主要特点&#xff1a;后进先出 存储结构的实现 顺序存储结构 链式存储结构 用途&#xff1a;通常作为一种临时存放数据的容器。如果后存入的元素先处理则使用栈。比如用于保存函…...

PostgreSQL 源码部署

文章目录 说明1. 准备工作1.1 源码包下载1.2 解压安装目录1.3 安装依赖包1.4 添加用户1.5 创建数据目录 2. 编译安装2.1 源码编译2.2 配置环境变量2.3 初始化数据库2.4 启动数据库2.5 连接数据库 3. 参数调整3.1 配置 pg_hba3.2 监听相关2.4 日志文件2.5 内存参数 说明 本篇文…...

医疗IT系统安科瑞隔离电源装置在医院的应用

【摘要】介绍该三级综合医院采用安科瑞隔离电源系统5件套&#xff0c;使用落地式配电柜安装方式&#xff0c;从而实现将TN系统转化为IT系统&#xff0c;以及系统绝缘情况监测。 【关键词】医用隔离电源系统&#xff1b;IT系统&#xff1b;绝缘情况监测&#xff1b;三级综合医院…...

高压放大器在3D打印中的应用

随着3D打印技术的快速发展&#xff0c;高压放大器在3D打印中的应用越来越受到人们的关注。高压放大器在3D打印中扮演着非常重要的角色&#xff0c;可以提高3D打印的效率和精度&#xff0c;从而实现更高的打印质量。本文将详细介绍高压放大器在3D打印中的应用及其原理。 高压放…...

chatgpt赋能python:Python中的三角函数介绍

Python中的三角函数介绍 Python作为一种高级编程语言&#xff0c;可以处理基础算术运算、三角函数等高等数学的操作。其中&#xff0c;三角函数是常用的数学函数之一&#xff0c;Pyhon中的三角函数包括正弦函数、余弦函数、正切函数等。 正弦函数 正弦函数在三角学中是最基本…...

异常检测论文1

本文仅作为个人阅读文献&#xff0c;做笔记记录。 <> \usepackage[dvipsnames]{xcolor} 一、摘要部分&#xff1a; 我们发现&#xff0c;现有的数据集偏向于局部结构异常&#xff0c;如划痕、凹痕或污染。特别是&#xff0c;它们缺乏违反逻辑约束形式的异常&#xff0…...

linux搭建hadoop环境

1、安装JDK   &#xff08;1&#xff09;下载安装JDK&#xff1a;确保计算机联网之后命令行输入下面命令安装JDK    sudo apt-get install sun-java8-jdk   &#xff08;2&#xff09;配置计算机Java环境&#xff1a;打开/etc/profile&#xff0c;在文件最后输入下面…...

02 Maven创建及使用

maven作用 主要用作基于java平台的项目 maven能提供一种项目配置 maven能自动从maven的中央仓库帮我们自动下载并管路项目依赖的jar包 提供了标准的目录结构 中央仓库两种类型:共有的中央仓库:私有中央仓库 使用mvn -v查看是否安装成功 修改本地仓库的的位置 在setting…...

如何在 Rocky Linux 上检查磁盘空间?

在 Rocky Linux 上检查磁盘空间是系统管理和维护的重要任务之一。磁盘空间的监控和管理可以帮助我们及时发现和解决存储空间不足的问题&#xff0c;以确保系统的正常运行。本文将详细介绍在 Rocky Linux 上检查磁盘空间的方法。 方法 1&#xff1a;使用 df 命令 df 命令是 Li…...

【软考系统规划与管理师笔记】第2篇 信息技术知识1

目录 1 软件工程 1.1 软件需求分析与定义 1.2 软件设计、测试与维护 1.3 软件质量保证及质量评价 1.4 软件配置管理 1.5 软件过程管理 1.6 软件复用 2 面向对象系统分析与设计 2.1 面向对象设计的基本概念 2.2统一建模语言与可视化建模 3. 应用集成技术 3.1 数据库与…...

【无标题】ELISA-3(加装跟踪装置)—让群体协作更智能!

群体智能是近年来发展迅速的一个人工智能学科领域&#xff0c;通过对蚂蚁、蜜蜂等为代表的社会性昆虫群体行为的研究&#xff0c;实现分布式等智能行为。作为新一代人工智能的重要方向&#xff0c;群体智能通常用于无人机、机器人集群的协同作业。目前&#xff0c;群体智能在基…...

Dubbo源码解析一服务暴露与发现

Dubbo 服务暴露与发现 1. Spring中自定义Schema1.1 案例使用1.2 dubbo中的相关对象 2. 服务暴露机制2.1 术语解释2.2 流程机制2.3 源码分析2.3.1 导出入口2.3.2 导出服务到本地2.3.3 导出服务到远程(重点)2.3.4 开启Netty服务2.3.5 服务注册2.3.6 总结 3. 服务发现3.1 服务发现…...

有哪些工具软件一旦用了就离不开?

&#x1f496;前言 目前&#xff0c;随着科技的快速发展&#xff0c;电脑已经进入了许许多多人的生活 &#xff0c;在平日的学习、工作和生活里&#xff0c;我们会用的各种各样的强大软件。市面上除了某些大公司开发在强大软件&#xff0c;还有各路大神开发具有某些功能的强大…...

ObjectARX如何判断点和多段线的关系

目录 1 基本思路2 相关知识点2.1 ECS坐标系概述2.2 其他点坐标转换接口2.3 如何获取多段线的顶点ECS坐标 3 实现例程3.1 接口实现3.2 测试代码 4 实现效果 在CAD的二次开发中&#xff0c;点和多段线的关系是一个非常重要且常见的问题&#xff0c;本文实现例程以张帆所著《Objec…...

四、DRF序列化器create方法与update方法

上一章&#xff1a; 二、Django REST Framework (DRF)序列化&反序列化&数据校验_做测试的喵酱的博客-CSDN博客 下一章&#xff1a; 五、DRF 模型序列化器ModelSerializer_做测试的喵酱的博客-CSDN博客 一、背景 1、创建请求&#xff0c;post&#xff0c;用户输入…...