c++二叉搜索树

文章目录

  • 一、二叉搜索树的概念
  • 二、二叉搜索树性能分析
  • 三、二叉搜索树的插入
  • 四、二叉搜索树的查找
  • 五、二叉搜索树的删除
  • 六、二叉搜索树完整代码
  • 七、二叉搜索树key和key/value使用场景

一、二叉搜索树的概念

1.二叉搜索树,是一个空树或者具有以下性质的二叉树:

若左子树不为空,那么左子树上所有结点的值都小于等于<=根结点的值

若右子树不为空,那么右子树上所有结点的值都大于等于>=根结点的值

左右子树也分别为二叉搜索树

2.二叉搜索树又称作二叉排序树,原因:

当二叉搜索树进行中序遍历时,左根右,所遍历出来的结果是升序的

3.二叉搜索树既可以支持插入相等的值,也可以不支持插入相等的值

map/set/multimap/multiset的底层就是二叉搜索树

其中map/set不支持插入相等的值,multimap/multiset支持插入相等的值

二、二叉搜索树性能分析

1.最优情况下,二叉搜索树为完全二叉树(接近于完全二叉树)高度为logN

此时查找的时间复杂度为logN

2.最差情况下,二叉搜索树退化为单支树(或类似于单支)高度为N

此时查找的时间复杂度为N

3.结合1和2得出二叉搜索树的查找时间复杂度为N

4.二叉搜索树的插入、删除、查找时间复杂度为N、

5.为了解决二叉搜索树的查找时间复杂度为N的问题,也就是为了避免出现单支树的情况

所以后续会引出平衡二叉搜索树(AVL树 or 红黑树)

平衡二叉树就会使得查找的时间复杂度为logN

6.另外,二分查找也可以使得查找的效率为logN,但是二分查找有两个显著缺陷:

(1)二分查找要求存储在支持下标[]随机访问的结构中,并且有序

(2)正因为二分查找存储在支持下标[]随机访问的结构中,所以当需要插入和删除数据时

效率低下,插入删除需要挪动数据

三、二叉搜索树的插入

1.二叉搜索树的结构

2.插入具体过程:

(1)如果_root根结点为nullptr,那么直接在_root根节点位置进行插入

(2)如果_root不为nullptr,那么根据二叉搜索树的性质与当前结点进行比较

如果插入的值小于当前结点,那么往当前结点的左子树走

如果插入的值大于当前结点,那么往当前结点的右子树走

找到空位置进行插入

(3)如果支持插入相等的值,插入的值根当前结点的值一样,那么既可以往左走也可以往

右走找到空位置,插入新结点(要注意保持逻辑的一致性,插入相等的值不要一会

往左走,一会儿往右走)

3.当二叉搜索树插入之后,那么为了看到输出,需要写遍历,而二叉搜索树的遍历只有中序

遍历才是有意义的

但是中序遍历是递归,递归是需要传参的,而参数为_root也就是根结点私有成员

在类外是无法访问到私有成员的,所以我们可以对这种情况进行封装

四、二叉搜索树的查找

1.从根结点开始比较,查找x,如果x比根的值小就往左查找,如果x比根的值大就往右查找

2.最多查找高度次,如果走到空还没有找到,那么该值不存在

3.如果不支持插入相等的值,那么查到到x就进行返回

4.如果支持插入相等的值,意味着着有多个x存在,一般情况下查找到第一个就进行返回

五、二叉搜索树的删除

1.删除的结点为叶子结点,左右子树皆为空

将该结点的父结点的指向改为nullptr,直接删除该结点

2.删除的结点左子树为空,右子树不为空

将该结点的父结点的指向改为该结点的右子树,然后删除该结点

3.删除的结点右子树为空,左子树不为空

将该结点的父结点的指向改为该节点的左子树,如果删除该结点

4.根据2和3,就可以将1划为2or3中的其中一类

(1)删除叶子结点,左右子树皆为空,就可以归为左子树为空/右子树为空

(2)将删除的叶子结点的父结点的指向改为叶子结点的左子树or右子树也就是nullptr

5.删除的结点左右子树皆不为空

(1)找到左子树中最右的结点(最大结点)

该结点一定比整个左子树要大,但是比右子树要小,可以跟被删除的结点进行替换

(2)或者找到右子树的最左结点(最小结点)

该结点一定比整个右子树要小,但是比左子树要大,可以跟被删除的结点进行替换

(3)替换过后,此时需要删除的结点就在左子树的最右or右子树的最左

(4)左子树的最右结点一定是可以直接删除的,因为该结点肯定没有右子树

无论是否有左子树,只需要将最右结点的父结点的指向改为该结点的左子树即可

(5)右子树的最左结点一定是可以直接删除的,因为该结点肯定没有左子树

无论是否有右子树,只需要将最左结点的父结点的指向该为该结点的右子树即可

六、二叉搜索树完整代码

1.二叉搜索树深拷贝与析构

(1)拷贝构造

(2)赋值运算符重载

(3)析构函数

2.完整代码

七、二叉搜索树key和key/value使用场景

1.key场景

(1)key场景就只是单纯的查找

(2)例1:

小区停车场识别车辆进入

将购买车位的车辆的号码牌进行存储,然后当车辆进入时查找该车牌号是否在

二叉搜索树中,在就抬杆让车辆进入,不在就输出非小区车辆禁止入内

(3)例2:

检查⼀篇英文文章单词拼写是否正确

将词库中所有单词放入二叉搜索树,读取文章中的单词,查找是否在二叉搜索树中,

不在则波浪线标红提示

2.key/value场景

(1)存储key时附带存储相关的value

(2)查找key时可以顺带查找到value,通过key找到value

(3)在二叉搜索树的核心逻辑中value不参与

(4)二叉搜索树中是不支持key进行修改,因为会影响整个二叉搜索树的结构

但是在key_value的场景下,value是可以进行修改的

(5)例1:

商场停车场是需要收费的,那么车辆在进入时不仅仅需要存储车辆的车牌号,还需要

车辆的入场时间,那么就可以使用key/value的场景,key存储车辆的车票号,value

存储入场时间

(6)例2:

简单中英互译字典,树的结构中(结点)存储key(英文)和vlaue(中文),

搜索时输入英文,则同时查找到了英文对应的中文

(7)例3:

统计一篇文章中单词出现的次数,读取一个单词,查找单词是否存在,不存在这个说

明第一次出现存储(单词,1),单词存在,则++单词对应的次数

key为单词,value为次数(key不可以改变,value可以改变)

(8)key/value实现代码

只需要在实现关于入数据的代码时,添加value即可

value不参与二叉搜索树的核心逻辑,二叉搜索树的核心逻辑都是根据key进行操作

相关推荐
咔咔咔的4 小时前
3000. 对角线最长的矩形的面积
c++
Sapphire~4 小时前
重学JS-004 --- JavaScript算法与数据结构(四)JavaScript 表单验证
前端·javascript·数据结构·算法
ShineWinsu6 小时前
对于牛客网—语言学习篇—编程初学者入门训练—复合类型:BC136 KiKi判断上三角矩阵及BC139 矩阵交换题目的解析
c语言·c++·学习·算法·矩阵·数组·牛客网
可可睡着辽10 小时前
C++链表双杰:list与forward_list
c++·链表·list
Jayden_Ruan12 小时前
C++计算正方形矩阵对角线和
数据结构·c++·算法
李白同学12 小时前
C++:list容器--模拟实现(下篇)
开发语言·数据结构·c++·windows·算法·list
z203483152013 小时前
C++抽象类
c语言·c++
不会学习?13 小时前
数据结构 第三轮
数据结构·经验分享·笔记·其他
ajassi200015 小时前
开源 C++ QT Widget 开发(八)网络--Http文件下载
网络·c++·开源