这是一棵适合搜索二叉树

🎈个人主页:🎈 :✨✨✨初阶牛✨✨✨
🐻强烈推荐优质专栏: 🍔🍟🌯C++的世界(持续更新中)
🐻推荐专栏1: 🍔🍟🌯C语言初阶
🐻推荐专栏2: 🍔🍟🌯C语言进阶
🔑个人信条: 🌵知行合一
🍉本篇简介:>:"二叉搜索树"的模拟实现
金句分享:
✨远赴人间惊鸿宴,一睹人间盛世颜!✨

目录

  • 一、什么是"二叉搜索树"?
  • 二、"二叉搜索树"的实现
    • 结点结构
    • "二叉搜索树":的结构
    • (1) "插入"操作
    • (2) "查找"操作
    • (3) "删除"操作 (重点)
    • (4)"中序"遍历
  • 三、结语

一、什么是"二叉搜索树"?

二叉搜索树(Binary Search Tree)又称为二叉查找树,是一种常用的数据结构。它是一棵空树,或者是具有以下性质的二叉树:

  1. 左子树上所有结点的值都小于它的根结点的值。
  2. 右子树上所有结点的值都大于它的根结点的值。
  3. 左右子树也分别为二叉搜索树。

错误示例1:
在这里插入图片描述
错误示例2:
在这里插入图片描述

正确示例:
在这里插入图片描述

二、"二叉搜索树"的实现

本篇文章实现的是键值对也就是(key,value)版本的 “二叉搜索树”.
Key-value版本的二叉搜索树(BST)是一种基于二叉树数据结构的数据结构,其中每个节点都存储一个键-值对。在该数据结构中,每个节点都具有一个唯一的关键字,该关键字用于对节点进行排序.

如下是树中每个结点的结构:

结点结构

template<class K, class V>
struct BSTreeNode
{BSTreeNode(const K& key = K(), const V& value = V()): _left(nullptr), _right(nullptr), _key(key), _value(value){}BSTreeNode<K,V>* _left;BSTreeNode<K,V>* _right;K _key;							//关键码,用于比较大小的,按key比较V _value;						//用于存储数据
};

“二叉搜索树”:的结构

template<class K, class V>
class BSTree
{typedef BSTreeNode<K, V> Node;		//注意这里的类型重命名
public:bool Insert(const K& key, const V& value);Node* Find(const K& key);bool Erase(const K& key);void _InOrder(Node* root);void InOrder();
private:Node* _root = nullptr;
};

(1) "插入"操作

根据"二叉搜索树"的特性,我们不难知道,左子树 < 根 < 右子树.

  1. 如果是空树,则表明新插入的结点将作为根节点.
  2. 如果不是空树,则先找到该插入的位置,再链接即可.

示例:如果在插入一个结点值为9的结点.

寻找过程:
比根节点8大,所以往右找.
12小,所以往左找.
11小,所以往左找.
11的左边为空,寻找结束.

9结点插入到11的左边.

在这里插入图片描述

//插入操作
template<class K, class V>
bool BSTree<K,V>::Insert(const K& key, const V& value)
{//如果是空树,则直接赋值给根节点if (_root == nullptr){//没看清node结构的,可以翻到上面在看一下构造函数._root = new Node(key,value);	//用值构建结点,并赋给根节点return true;}//如果不是 空树Node* cur = _root;			//代替根节点遍历树,寻找插入位置.Node* pnode = nullptr;		//记录目标位置的父亲结点while (cur)				//一直找到nullptr为止{pnode = cur;				//更新父节点if (key > cur->_key)		//如果插入的键值对 key 比当前元素的key大,则往右走{cur = cur->_right;}else if (key < cur->_key)		//如果插入的值比当前元素小,则往左走{cur = cur->_left;}else return false;			//相等则返回false}//判断插入在左边还是右边Node* newnode = new Node(key, value);if (key < pnode->_key){pnode->_left = newnode;}else{pnode->_right = newnode;}return true;
}

(2) "查找"操作

友友们插入操作都能轻松拿捏,那find还不是轻松拿捏?

小注意:
如果函数是在类里面声明,类外面定义,则需要注意一个小问题.
Node是一个类型还是一个变量(静态成员变量可以通过类名+ ::访问),所以需要在前面加上一个关键字typename ,告诉编译器这是一个类型.

template<class K, class V>
typename BSTree<K,V>::Node* BSTree<K, V>::Find(const K& key)
{Node* cur = _root;			//代替根节点遍历树.while (cur){if (key > cur->_key)		//如果查找的值比当前元素大,则往右走{cur = cur->_right;}else if (key < cur->_key)		//如果查找的值比当前元素小,则往左走{cur = cur->_left;}else return cur;			//相等则说明找到了}return nullptr;
}

(3) "删除"操作 (重点)

删除操作应该是"二叉搜索树"最难的操作了,这里牛牛就讲解的仔细一点吧!

(1)情况1: 目标结点没有孩子.
处理方法:找到该结点 和 该结点的父亲,直接删除即可.
在这里插入图片描述

(2)情况2:目标结点只有一个孩子,可能是左孩子,也可能是右孩子.
处理方法:
只有左孩子时:
让父亲不再指向自己(这里要判断自己在父亲的左还是右),而是指向自己的左孩子,然后再删除自己.
在这里插入图片描述

只有右孩子时:
让父亲不再指向自己(这里要判断自己在父亲的左还是右),而是指向自己的右孩子,然后再删除自己.
在这里插入图片描述

情况3: 目标结点有两个孩子.

右子树最小节点:
在这里插入图片描述

左子树最大节点:
在这里插入图片描述

代码实现:

template<class K, class V>
bool BSTree<K, V>::Erase(const K& key)
{if (_root == nullptr){cout << "空树不可删除" << endl;//空树无法删除return false;}//寻找目标结点的位置Node* pnode = nullptr;		//记录当前结点的父亲结点Node* cur = _root;			//当前结点:代替根节点遍历树.//寻找目标结点while (cur){if (key > cur->_key)		//如果插入的值比当前元素大,则往右走{pnode = cur;cur = cur->_right;}else if (key < cur->_key)		//如果插入的值比当前元素小,则往左走{pnode = cur;cur = cur->_left;}else  break;			//相等则说明找到了}//表示在树中 未找到if (cur == nullptr) { return false; }//这里采取与右子树的最小结点替换的方法if (cur->_right && cur->_left)//如果有两个孩子{Node* p_left_max = nullptr;			//右树 的最小节点的父亲Node* left_max = cur->_right;		//右树 的最小节点//寻找目标结点 右树 的最小节点while (left_max->_left){p_left_max = left_max;left_max = left_max->_left;}//替换cur->_key = left_max->_key;		//其实覆盖即可cur->_value = left_max->_value;//将原右子树的最小结点的父亲与 右树最小结点断绝关系p_left_max->_left = nullptr;delete left_max;					//删除右树最小结点return true;}// 要删除的节点只有一个子节点或没有子节点Node* child = nullptr;//这样child就是孩子if (cur->_left)	//只有左孩子{child = cur->_left;}else//只有右孩子或者没有孩子{child = cur->_right;}if (pnode == nullptr) // 根节点要删除的情况_root = child;else if (pnode->_left == cur) // 要删除的节点是父节点的左子节点pnode->_left = child;else // 要删除的节点是父节点的右子节点pnode->_right = child;delete cur;return true;
}

(4)"中序"遍历

学过二叉树的友友,对于这个,没啥好说的吧.

补充小技巧.

由于我们在类外面调用中序遍历函数需要传递root结点,但是root结点是私有成员变量,在类外面无法获取.
对象名.InOrder();

优秀的解决方法:
再嵌套一层,类里面的函数可以直接获取私有成员变量root,所以我们可以利用这一点.

template<class K, class V>
void  BSTree<K, V>::InOrder()
{if (_root == nullptr){cout << "空树" << endl;return;}_InOrder(_root);		//这里调用即可
}

类中:

template<class K, class V>
class BSTree
{typedef BSTreeNode<K, V> Node;
public:void _InOrder(Node* root);void InOrder();
private:Node* _root = nullptr;
};

真正的中序遍历:


template<class K, class V>
void  BSTree<K, V>::_InOrder(Node* root)
{if (root == nullptr)return;_InOrder(root->_left);cout << root->_key << "->" << root->_value << endl;_InOrder(root->_right);
}

三、结语

好的,到这里二叉搜索树就实现完毕了,二叉搜索树可是很优秀的一种数据结构呢!
搜索数据的时间复杂度在O(logn)级别,因为每判断一次,就可以舍去一半的子树(大往右子树找,小往左子树找),这样就是高度层.

当然,搜索二叉树也是有明显的缺点的,到时候我们在AVL树中介绍吧!

在这里插入图片描述

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

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

相关文章

宏集新闻 | 虹科传感器事业部正式更名为宏集科技

致一直支持“虹科传感器”的朋友们&#xff1a; 为进一步整合资源&#xff0c;给您带来更全面、更优质的服务&#xff0c;我们非常荣幸地宣布&#xff0c;虹科传感器事业部已正式更名为宏集科技。这一重要的改变代表了虹科持续发展进程中的新里程碑&#xff0c;也体现了我们在传…

安装gitlab

安装gitlab 环境 关闭防火墙以及selinux&#xff0c;起码4核8G 内存至少 3G 不然启动不了 下载环境 gitlab官网&#xff1a;GitLab下载安装_GitLab最新中文基础版下载安装-极狐GitLab rpm包下载地址&#xff1a; [Yum - Nexus Repository Manager (gitlab.cn)](https://pack…

Android studio run 手机或者模拟器安装失败,但是生成了debug.apk

错误信息如下&#xff1a;Error Installation did not succeed. The application could not be installed&#xff1a;List of apks 出现中文乱码&#xff1b; 我首先尝试了打包&#xff0c;能正常安装&#xff0c;再次尝试了debug的安装包&#xff0c;也正常安装&#xff1…

报错!Jupyter notebook 500 : Internal Server Error

Jupyter notebook 报错 500 : Internal Server Error 问题背景 tensorflow-gpu环境&#xff0c;为跑特定代码专门开了一个环境&#xff0c;使用conda安装了Jupyter notebook&#xff0c;能够在浏览器打开Jupyter notebook&#xff0c;但是notebook打开ipynb会报错。 问题分析…

抖音seo矩阵系统源代码部署及产品功能设计分析

一、引言 随着抖音等短视频平台的崛起&#xff0c;越来越多的企业和个人开始关注如何在这些平台上提升曝光量和用户流量。抖音SEO&#xff08;搜索引擎优化&#xff09;是一种有效的方法&#xff0c;通过优化短视频内容和关键词&#xff0c;让更多的人找到并点击你的视频。本文…

【css】Google第三方登录按钮样式修改

文章目录 场景前置准备修改样式官方属性修改样式CSS修改样式按钮的高度height和border-radiusLogo和文字布局 场景 需要用到谷歌的第三方登录&#xff0c;登录按钮有自己的样式。根据官方文档&#xff1a;概览 | Authentication | Google for Developers&#xff0c;提供两种第…

【Web】Ctfshow Nodejs刷题记录

目录 ①web334 ②web335 ③web336 ④web337 ⑤web338 ⑥web339 ⑦web340 ⑧web341 ⑨web342-343 ⑩web344 ①web334 进来是一个登录界面 下载附件&#xff0c;简单代码审计 表单传ctfshow 123456即可 ②web335 进来提示 get上传eval参数执行nodejs代码 payload: …

基于安卓android微信小程序的个人管理小程序

运行环境 开发语言&#xff1a;Java 框架&#xff1a;ssm JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&a…

B站短视频如何去水印?一键解析下载B站视频!

在浏览B站视频时&#xff0c;我们有时会遇到带有水印的场景。这些水印可能会干扰我们对视频内容的观看体验&#xff0c;特别是在全屏观看时。此外&#xff0c;当我们想要保存或分享这些视频时&#xff0c;水印也会成为一种障碍。因此&#xff0c;去除水印的需求就变得非常迫切。…

035、目标检测-物体和数据集

之——物体检测和数据集 目录 之——物体检测和数据集 杂谈 正文 1.目标检测 2.目标检测数据集 3.目标检测和边界框 4.目标检测数据集示例 杂谈 目标检测是计算机视觉中应用最为广泛的&#xff0c;之前所研究的图片分类等都需要基于目标检测完成。 在图像分类任务中&am…

wsl安装ubuntu的问题点、处理及连接

WSL安装Ubuntu的参考链接 (41条消息) wsl报错&#xff1a;WslRegisterDistribution failed with error: 0x800701bc_yzpyzp的博客-CSDN博客_0x800701bc wsl (41条消息) 使用Ubuntu安装软件出现Unable to locate package错误解决办法_大灰狼学编程的博客-CSDN博客 手把手教你…

栈的生长方向不总是向下

据我了解&#xff0c;栈的生长方向向下&#xff0c;内存地址由高到低 测试 windows下&#xff1a; 符合上述情况 测试Linux下&#xff1a; 由此可见&#xff0c;栈在不同操作系统环境下&#xff0c;生长方向不总是向下

时序预测 | MATLAB实现基于LSTM-AdaBoost长短期记忆网络结合AdaBoost时间序列预测

时序预测 | MATLAB实现基于LSTM-AdaBoost长短期记忆网络结合AdaBoost时间序列预测 目录 时序预测 | MATLAB实现基于LSTM-AdaBoost长短期记忆网络结合AdaBoost时间序列预测预测效果基本介绍模型描述程序设计参考资料 预测效果 x 基本介绍 1.Matlab实现LSTM-Adaboost时间序列预测…

Android HAL学习 及 与BSP的区别

Android HAL学习 及 与BSP的区别 参考链接&#xff1a; 1、https://www.cnblogs.com/looner/articles/11579335.html 2、https://blog.csdn.net/leesan0802/article/details/124087630 3、https://zhuanlan.zhihu.com/p/336531442 在HAL的学习之前&#xff0c;我们来先了解…

京东数据分析(京东数据采集):2023年10月京东平板电视行业品牌销售排行榜

鲸参谋监测的京东平台10月份平板电视市场销售数据已出炉&#xff01; 根据鲸参谋电商数据分析平台的相关数据显示&#xff0c;10月份&#xff0c;京东平台上平板电视的销量将近77万&#xff0c;环比增长约23%&#xff0c;同比则下降约30%&#xff1b;销售额为21亿&#xff0c;环…

数据库数据恢复—MongoDB数据库文件拷贝出现错误的数据恢复案例

MongoDB数据库数据恢复环境&#xff1a; 一台Windows Server操作系统的虚拟机&#xff0c;虚拟机上部署有MongoDB数据库。 MongoDB数据库故障&检测&#xff1a; 在未关闭MongoDB服务的情况下&#xff0c;工作人员将MongoDB数据库文件拷贝到其他分区&#xff0c;然后将原数…

双12电视盒子推荐:测评员解析目前电视盒子哪个最好

电视盒子不需要每月缴费&#xff0c;只需联网就可以收看海量视频资源&#xff0c;游戏、网课、投屏等功能让电视盒子的使用场景更丰富&#xff0c;我每年都会进行数十次电视盒子测评&#xff0c;本期要分享的是双十二电视盒子推荐&#xff0c;全面解析目前电视盒子哪个最好。 一…

UE4基础篇十七:分析性能

一、性能瓶颈定位 原文地址:小能猫吃牙膏:UE4 性能 - (一)瓶颈定位 P.S. 对于某个具体问题,我个人偏向于遵循 WHY → WHAT → HOW 的思考方法(重要性逐级递减) 加以理解。因为如果找不到做某件事情的意义(WHY)所在,或是对这件事情本身的定义(WHAT)都模棱两可,那么即便经…

计算机视觉与机器学习D1

计算机视觉简介 技术背景 了解人工智能方向、热点 目前人工智能的技术方向有&#xff1a; 1、计算机视觉——计算机视觉(CV)是指机器感知环境的能力&#xff1b;这一技术类别中的经典任务有图像形成、图像处理、图像提取和图像的三维推理。物体检测和人脸识别是其比较成功…

什么是凸函数

假设函数是定义在某个向量空间的凸子集上的实值函数&#xff0c;并且&#xff0c;如果对于中的任何两个向量和&#xff0c;都满足&#xff1a; 则称为上的凸函数