【1++的数据结构】之二叉搜索树

👍作者主页:进击的1++
🤩 专栏链接:【1++的数据结构】


文章目录

  • 一,什么是二叉搜索树
  • 二,二叉搜索树的操作及其实现
    • 2.1 插入操作及其实现
    • 2.2 查找操作及其实现
    • 2.3 删除操作及其实现
  • 三,构造及其析构
  • 四,二叉搜索树的应用

在这里插入图片描述

一,什么是二叉搜索树

二叉搜索书又叫二叉排序树或二叉查找树,其左子数上的节点小于根节点;右子树上的节点大于根节点。
如图,就是一颗二叉搜索树。
在这里插入图片描述

二,二叉搜索树的操作及其实现

2.1 插入操作及其实现

二叉搜索树的插入其先根据插入值的大小确定插入的位置,并且,若是有相同的值则不会进行插入。确定位置的依据是我们上述的二叉搜索树的特性:左子树上的节点小于根节点;右子树上的节点大于根节点。
当确定好位置后,我们申请节点,将新节点链接到树中。
下面是插入的两种实现:

  1. 非递归:
typedef BSTreeNode<K> Node;public:bool Insert(const K& key){if (_root == nullptr){_root = new Node(key);return true;}Node* cur = _root;Node* parent = _root;//记录其父节点,方便链接while (cur != nullptr)//找位置{if (key < cur->_key){parent = cur;cur = cur->left;}else if (key > cur->_key){parent = cur;cur = cur->right;}else{return false;}}cur = new Node(key);//链接过程if (parent->_key > key){parent->left = cur;}else{parent->right = cur;}return true;}
  1. 递归
	bool InsertR(const K& key){return _InsertR(_root, key);}bool _InsertR(Node*& root,const K& key){if (root == nullptr)//为空则说明已经找好了位置,可以进行插入{Node* cur = new Node(key);root = cur;return true;}if (key < root->_key){_InsertR(root->left, key);}else if (key > root->_key){_InsertR(root->right, key);}else{return false;//遇到相同的值}return true;}

由于在类外无法访问根节点_root,所以无法给_InsertR()传参,因此我们,多写了一层函数,在类里面调用插入的递归函数。这里有一个非常重要的细节就是在传root时我们使用的是引用。这时我们就可以直接进行链接,不需要记录其父节点了。

2.2 查找操作及其实现

其查找利用其二叉搜索树的特性,当树为完全二叉树或满二叉树时,其效率可以达到lgN (N为数的高度)。
下面为查找的两种实现方法:

  1. 非递归:
bool Find(const K& key){Node* cur = _root;while (cur){if (key < cur->_key){cur = cur->left;}else if (key > cur->_key){cur = cur->right;}else{return true;}}return false;}
  1. 递归实现
bool _FindR(Node*& root, const K& key){if (root == nullptr){return false;}if (key < root->_key){_FindR(root->left, key);}else if (key > root->_key){_FindR(root->right, key);}else{return true;}}

2.3 删除操作及其实现

删除操作我们可以分为几种情况:

  1. 删除节点没有孩子
  2. 删除节点有右孩子
  3. 删除节点有左孩子
  4. 删除节点有左右孩子
    对这四种情况我们又可以进行合并,将1与2,3归为一类。
    对于有两个节点的情况,我们在找到要删除节点后,在找到右子树的最小值或左子树的最大值,将其值与删除节点值进行交换,这时,我们就只需要删除右子树最小值或左子树最大值了。
    需要注意的是:其右子树最小值或左子树最大值后可能还有节点,因此要进行判断。

非递归:

bool Erase(const K& key){Node* cur = _root;Node* parent = _root;while (cur != nullptr){if (key < cur->_key){parent = cur;cur = cur->left;}else if (key > cur->_key){parent = cur;cur = cur->right;}else{//左为空if (cur->left == nullptr){if (cur == _root){_root = cur->right;}else if (key < parent->_key){parent->left = cur->right;}else{parent->right = cur->right;}delete cur;}else if (cur->right == nullptr)//右为空{if (cur == _root){_root = cur->left;}else if (key < parent->_key){parent->left = cur->left;}else{parent->right = cur->left;}delete cur;}else//都不为空{//先找右子树的最小值Node* Minparent = cur;Node* Min=cur->right;while (Min->left != nullptr){Minparent = Min; Min = Min->left;}std::swap(Min->_key, cur->_key);if (Minparent->left == Min){Minparent->left = Min->right;}else{Minparent->right = Min->right;}delete Min;}return true;}}return false;}

递归:

	bool _EraseR(Node*& root, const K& key){if (root == nullptr){return false;}if (key < root->_key){_EraseR(root->left, key);}else if (key > root->_key){_EraseR(root->right, key);}else{Node* del = root;//找右子树最小if (root->left == nullptr){root = root->right;}else if (root->right == nullptr){root = root->left;}else{Node* min = root->right;//找右子树最小值while (min->left){min = min->left;}std::swap(root->_key, min->_key);return _EraseR(root->right, key);}delete del;return true;}}

三,构造及其析构

//拷贝构造BSTree(const BSTree<K>& t){_root = Copy_root(t._root);}Node* Copy_root(Node* root){if (root == nullptr){return nullptr;}Node* copy_root = new Node(root->_key);copy_root->left = Copy_root(root->left);copy_root->right = Copy_root(root->right);return copy_root;}//赋值重载BSTree& operator=(BSTree<K> T){std::swap(T._root,this->_root);return *this;}//析构~BSTree(){Destory(_root);}void Destory(Node* root){if (root == nullptr){return;}Destory(root->left);Destory(root->right);delete root;root = nullptr;}

拷贝构造有一些像前序遍历,我们遇到一个节点就构造一个节点,最后在递归返回时将其链接起来。
析构函数则是像后续遍历。

四,二叉搜索树的应用

  1. K模型:K模型即只有key作为关键码,结构中只需要存储Key即可,关键码即为需要搜索到的值。
  2. KV模型:每一个关键码key,都有与之对应的值Value,即<Key, Value>的键值对。如,中英文对照。

二叉搜索树的性能:对于插入和删除来说,都必须要先查找:插入查找插入的位置,删除查找删除的节点。因此其查找的性能代表了二叉树的性能。其查找的性能于树的深度有关,但对于同一个集合,其插入的顺序不同,那么形成的树也是不同的。我们期望的最好的情况是它能够形成一个完全二叉树或接近完全二叉树的树。此时他的查找的效率能够达到lgN;但其也有可能会形成一个单支树,此时效率最差,为N。
在这里插入图片描述

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

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

相关文章

分布式链路追踪概述

分布式链路追踪概述 文章目录 分布式链路追踪概述1.分布式链路追踪概述1.1.什么是 Tracing1.2.为什么需要Distributed Tracing 2.Google Dapper2.1.Dapper的分布式跟踪2.1.1.跟踪树和span2.1.2.Annotation2.1.3.采样率 3.OpenTracing3.1.发展历史3.2.数据模型 4.java探针技术-j…

TOMCAT部署及优化(Tomcat配置文件参数优化,Java虚拟机(JVM)调优)

TOMCAT tomcat &#xff1a;是一个开放源代码的web应用服务器&#xff0c;基于java代码开发的。也可以理解为tomacat就是处理动态请求和基于java代码的页面开发。可以在html当中写入java代码&#xff0c;tomcat可以解析html页面当中的java&#xff0c;执行动态请求&#xff0c;…

Java算法_ LRU 缓存(LeetCode_Hot100)

题目描述&#xff1a;请你设计并实现一个满足 LRU &#xff08;最近最少使用&#xff09; 缓存 约束的数据结构。 获得更多&#xff1f;算法思路:代码文档&#xff0c;算法解析的私得。 运行效果 完整代码 import java.util.HashMap; import java.util.Map;/*** 2 * Author: L…

makefile include 使用介绍

文章目录 前言一、include 关键字1. 语法介绍2. 处理方式示例&#xff1a; 二、- include 操作总结 前言 一、include 关键字 1. 语法介绍 在 Makefile 中&#xff0c;include 指令&#xff1a; 类似于 C 语言中的 include 。将其他文件的内容原封不动的搬入当前文件。 当 …

打破音频语言障碍,英语音频翻译成文字软件助你畅快对话

要理解外语歌曲对我来说难如登天。不过&#xff0c;这种痛苦没有持续太久&#xff0c;我发现了一种音频翻译技术&#xff0c;它像一个语言转换器&#xff0c;可以即时将外语歌曲翻译成我听得懂的语言&#xff01;我惊喜地试用后&#xff0c;终于可以在听歌的同时看到翻译的歌词…

QT压缩解压文件

文章目录 前言一、下载Quazip二、编译Quazip1.使用vs2019打开quazip.sln2.使用Qt VS Tools打开外层的.pro工程3.编译 三、工程使用1.配置头文件路径2.配置静态库lib目录3.添加库4.动态库dll放到.exe同级目录下5.使用 前言 Qt工程中需要用到zip压缩解压功能&#xff0c;网上搜索…

【Tool】win to go 制作随身硬盘

前言 话说我一冲动买了512G固态硬盘&#xff0c;原本是装个ubuntu系统的&#xff0c;这个好装&#xff0c;但是用处太少&#xff0c;就像改成win10的 经历一堆坑之后&#xff0c;终于使用WTG安装好了 步骤 1.下载个WTG辅助工具 Windows To Go 辅助工具|WTG辅助工具 v5.6.1…

leetcode - 75. 颜色分类(java)

颜色分类 leetcode - 75. 颜色分类题目描述双指针代码演示 双指针算法专题 leetcode - 75. 颜色分类 难度 - 中等 原题链接 - 颜色分类 题目描述 给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums &#xff0c;原地对它们进行排序&#xff0c;使得相同颜色的元素相邻&…

【安装部署】Mysql下载及其安装的详细步骤

1.下载压缩包 官网地址&#xff1a;www.mysql.com 2.环境配置 1.先解压压缩包 2.配置环境变量 添加环境变量&#xff1a;我的电脑--->属性-->高级-->环境变量-->系统变量-->path 3.在mysql安装目录下新建my.ini文件并&#xff0c;编辑my.ini文件 编辑内容如…

Centos7.9安装lrzsz进行文件传输---Linux工作笔记059

这里咱们lrzsz命令,需要用来进行文件传输,因为如果不安装这个命令的话,那么 传输安装包什么的就不方便因为只有少数传输工具,才支持,直接拖拽的.没有的时候就可以用这个工具,用命令来传输 直接就是: sz 文件名 就可以把文件下载下来 rz 选择一个文件, 就可以把文件上传到当…

FISCO BCOS V3.0 Air建链体验——对比V2.9建链差别

前提 好久不见&#xff0c;最近因为毕业的手续等问题&#xff0c;一直都没有更新&#xff0c;FISCO BCOS第二季task挑战赛如期展开啦&#xff0c;因为毕业的问题&#xff0c;也是非常遗憾的错过了上一期的task挑战赛&#xff0c;这一期一定双倍挑战&#xff0c;hhhhhh Air版本…

面试热题(单词搜索)

给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 单词必须按照字母顺序&#xff0c;通过相邻的单元格内的字母构成&#xff0c;其中“相邻”单元格是那些水平相邻或垂直相…

机器学习笔记 - 关于GPT-4的一些问题清单

一、简述 据报道,GPT-4 的系统由八个模型组成,每个模型都有 2200 亿个参数。GPT-4 的参数总数估计约为 1.76 万亿个。 近年来,得益于 GPT-4 等高级语言模型的发展,自然语言处理(NLP) 取得了长足的进步。凭借其前所未有的规模和能力,GPT-4为语言 AI​​设立了新标准,并为机…

【三维重建】【深度学习】instant-nsr-pl代码Pytorch实现--训练自己的数据集

【三维重建】【深度学习】instant-nsr-pl代码Pytorch实现–训练自己的数据集 基于Instant-NGP的神经表面重建&#xff1a;该存储库包含 NeRF 和 NeuS 的简洁且可扩展的实现&#xff0c;用于基于 Instant-NGP 和 Pytorch-Lightning 框架的神经表面重建&#xff0c;旨在为基于 Ne…

力扣初级算法(旋转矩阵)

力扣初级算法(旋转矩阵) 每日一算法&#xff1a;旋转矩阵 学习内容&#xff1a; 1.问题&#xff1a; 给你一幅由 N N 矩阵表示的图像&#xff0c;其中每个像素的大小为 4 字节。请你设计一种算法&#xff0c;将图像旋转 90 度。 不占用额外内存空间能否做到&#xff1f; 2.…

vue+springboot基于web的火车高铁铁路订票管理系统

铁路订票管理系统按照权限的类型进行划分&#xff0c;分为用户和管理员两个模块。管理员模块主要针对整个系统的管理进行设计&#xff0c;提高了管理的效率和标准。主要功能包括个人中心、用户管理、火车类型管理、火车信息管理、车票预订管理、车票退票管理、系统管理等&#…

uniapp-----封装接口

系列文章目录 uniapp-----封装接口 uniapp-----分包 文章目录 系列文章目录 uniapp-----封装接口 uniapp-----分包 文章目录 前言 一、技术 二、封装步骤 1.准备 ​编辑 2.代码填充 request.js&#xff1a; api.js&#xff1a; min.js 页面使用 总结 前言 uni…

mysql索引的数据结构(Innodb)

首选要注意,这里的数据结构是存储在硬盘上的数据结构,不是内存中的数据结构,要重点考虑io次数. 一.不适合的数据结构: 1.Hash:不适合进行范围查询和模糊匹配查询.(有些数据库索引会使用Hash,但是只能精准匹配) 2.红黑树:可以范围查询和模糊匹配,但是和硬盘io次数比较多. 二…

vue : 无法加载文件 C:\Users\…\npm\vue.ps1,因为在此系统上禁止运行脚本。

在 PowerShell 中创建 vue 项目时&#xff0c;出现了以下错误导致创建失败&#xff1a;vue : 无法加载文件 C:\Users\…\npm\vue.ps1&#xff0c;因为在此系统上禁止运行脚本。 报错原因 用户权限不足导致无法加载文件&#xff0c;以管理员身份运行终端或者 PowerShell 也可…

Go异常处理机制panic和recover

recover 使用panic抛出异常后, 将立即停止当前函数的执行并运行所有被defer的函数&#xff0c;然后将panic抛向上一层&#xff0c;直至程序crash。但是也可以使用被defer的recover函数来捕获异常阻止程序的崩溃&#xff0c;recover只有被defer后才是有意义的。 func main() { p…