【C++ 二叉搜索树】

目录

  • 1.什么是二叉搜索树
  • 2.构建二叉搜索树
    • 2.1首先搭建树的框架
    • 2.2搭建搜索树的框架
  • 3.二叉搜索树的插入
    • 3.1非递归式插入
    • 3.2递归式插入
  • 4.二叉搜索树的查找
    • 4.1非递归查找
    • 4.2递归查找
  • 5.二叉搜索树的删除
    • 5.1非递归删除
    • 5.2递归删除
  • 6.整个代码实现

1.什么是二叉搜索树

简单来讲就是一个树的左子树的值都小于根,右子树的值都大于根。如:
在这里插入图片描述
这个树的特点是走一趟中序就完成了对一组树的排序。查找一个树也特别的方便,最多只需要走树的高度次。所以当这个树比较饱满时搜索的效率很高,所以被称为二叉搜索树。

2.构建二叉搜索树

2.1首先搭建树的框架

struct TreeNode
{TreeNode<V>* _left;TreeNode<V>* _right;V _val;//构造函数TreeNode(V val){_left = nullptr;_right = nullptr;_val = val;}
};

2.2搭建搜索树的框架

template<class V>
class BSTree
{typedef TreeNode<V> Node;
public:BSTree(){_head = nullptr;}private:Node* _head;};

3.二叉搜索树的插入

3.1非递归式插入

1.思路
在这里插入图片描述
2.代码

//插入(非递归)bool insert(V val){if (_head == nullptr){_head = new Node(val);return true;}//找到要插入结点的位置Node* parent = _head;Node* cur = _head;while (cur){if (cur->_val < val){parent = cur;cur = cur->_right;}else if (cur->_val > val){parent = cur;cur = cur->_left;}else{//相等  返回falsereturn false;}}//判断val插在parent的左还是右if (parent->_val >val){parent->_left = new Node(val);return true;}else{parent->_right = new Node(val);return true;}

3.2递归式插入

	bool insertR(V val){return _insertR(_head, val);}bool _insertR(Node*& head, V val){if (head == nullptr){head = new Node(val);return true;}if (head->_val > val){_insertR(head->_left,val);}else if (head->_val < val){_insertR(head->_right, val);}else{return false;}return false;}

注意点:这个递归式插入其实也没什么难的,就是有个注意点是要引用传参。如果不是引用传参是不会修改-head的。

4.二叉搜索树的查找

4.1非递归查找

//非递归查找
bool find(V val)
{if (_head == nullptr){return false;}Node* cur = _head;while (cur){if (cur->_val < val){cur = cur->_right;}else if (cur->_val > val){cur = cur->_left;}else{return true;}}
}

4.2递归查找

bool findR(const V& val)
{return _findR(_head, val);
}bool _findR(Node* head, const V& val)
{if (head == nullptr){return false;}if (head->_val == val){return true;}return _findR(head->_left, val) || _findR(head->_right, val);
}

比较常规,没什么要解释的。

5.二叉搜索树的删除

5.1非递归删除

算法思路:
在这里插入图片描述

代码实现:

//非递归式删除
bool erase(const V& val)
{//第一步找到要删除的结点Node* parent = _head;Node* cur = _head;while (cur){if (cur->_val > val){parent = cur;cur = cur->_left;}else if (cur->_val < val){parent = cur;cur = cur->_right;}else{//找到了//分情况讨论if (cur->_left == nullptr){//特殊情况if (cur == _head){_head = _head->_right;return true;}if (parent->_left == cur){parent->_left = cur->_right;}else{parent->_right = cur->_right;}delete cur;return true;}else if (cur->_right == nullptr){//特殊情况if (cur == _head){_head = _head->_left;return true;}if (parent->_left == cur){parent->_left = cur->_left;}else{parent->_right = cur->_left;}delete cur;return true;}else{//找LeftMaxNode* parent = cur;Node* LeftMax = cur->_left;while (LeftMax->_right){parent = LeftMax;LeftMax = LeftMax->_right;}//交换cur与LeftMax的valswap(cur->_val, LeftMax->_val);if (parent->_left == LeftMax){parent->_left = LeftMax->_right;}else{parent->_right = LeftMax->_right;}delete LeftMax;return true;}}}return false;
}

注:这个非递归主要就是要完全考虑到删除结点会出现的可能,代码实现不复杂,但是很难一起写对,写错了调试也好很久(本人亲身经历调试了一个下午)。

5.2递归删除

算法思路:
在这里插入图片描述

代码实现:

bool _eraseR(Node*& head, const V& val){if (head == nullptr){return false;}else if (head->_val > val){_eraseR(head->_left, val);}else if (head->_val < val){_eraseR(head->_right, val);}else{//递归找到了Node* del = head;//三种情况//1.左子树为空if (head->_left == nullptr){head = head->_right;}//2.右子树为空else if(head->_right == nullptr){head = head->_left;}//3.左右子树都不为空else{//找LeftMaxNode* LeftMax = head->_left;while (LeftMax->_right){LeftMax = LeftMax->_right;}//交换swap(head->_val, LeftMax->_val);//递归删除return _eraseR(head->_left, val);}delete del;return true;}}

6.整个代码实现

#pragma once
template<class V>
struct TreeNode
{TreeNode<V>* _left;TreeNode<V>* _right;V _val;//构造函数TreeNode(V val){_left = nullptr;_right = nullptr;_val = val;}
};template<class V>
class BSTree
{typedef TreeNode<V> Node;
public:BSTree(){_head = nullptr;}//深拷贝BSTree(BSTree<V>& bs){_head = CopyTree(bs._head);}//赋值BSTree<V>& operator=(BSTree<V> bs){swap(_head, bs._head);return *this;}//插入(非递归)bool insert(V val){if (_head == nullptr){_head = new Node(val);return true;}//找到要插入结点的位置Node* parent = _head;Node* cur = _head;while (cur){if (cur->_val < val){parent = cur;cur = cur->_right;}else if (cur->_val > val){parent = cur;cur = cur->_left;}else{//相等  返回falsereturn false;}}//判断val插在parent的左还是右if (parent->_val >val){parent->_left = new Node(val);return true;}else{parent->_right = new Node(val);return true;}}bool insertR(V val){return _insertR(_head, val);}//非递归查找bool find(V val){if (_head == nullptr){return false;}Node* cur = _head;while (cur){if (cur->_val < val){cur = cur->_right;}else if (cur->_val > val){cur = cur->_left;}else{return true;}}}bool findR(const V& val){return _findR(_head, val);}~BSTree(){destory(_head);}void inorder(){_inorder(_head);cout << endl;}//非递归式删除bool erase(const V& val){//第一步找到要删除的结点Node* parent = _head;Node* cur = _head;while (cur){if (cur->_val > val){parent = cur;cur = cur->_left;}else if (cur->_val < val){parent = cur;cur = cur->_right;}else{//找到了//分情况讨论if (cur->_left == nullptr){//特殊情况if (cur == _head){_head = _head->_right;return true;}if (parent->_left == cur){parent->_left = cur->_right;}else{parent->_right = cur->_right;}delete cur;return true;}else if (cur->_right == nullptr){//特殊情况if (cur == _head){_head = _head->_left;return true;}if (parent->_left == cur){parent->_left = cur->_left;}else{parent->_right = cur->_left;}delete cur;return true;}else{//找LeftMaxNode* parent = cur;Node* LeftMax = cur->_left;while (LeftMax->_right){parent = LeftMax;LeftMax = LeftMax->_right;}//交换cur与LeftMax的valswap(cur->_val, LeftMax->_val);if (parent->_left == LeftMax){parent->_left = LeftMax->_right;}else{parent->_right = LeftMax->_right;}delete LeftMax;return true;}}}return false;}bool eraseR(const V& val){return _eraseR(_head, val);}private:Node* _head;void destory(Node*& head){if (head == nullptr){return;}destory(head->_left);destory(head->_right);delete head;head = nullptr;}bool _insertR(Node*& head, V val){if (head == nullptr){head = new Node(val);return true;}if (head->_val > val){_insertR(head->_left,val);}else if (head->_val < val){_insertR(head->_right, val);}else{return false;}return false;}void _inorder(Node* head){if (head == nullptr){return;}_inorder(head->_left);cout << head->_val << " ";_inorder(head->_right);}bool _findR(Node* head, const V& val){if (head == nullptr){return false;}if (head->_val == val){return true;}return _findR(head->_left, val) || _findR(head->_right, val);}bool _eraseR(Node*& head, const V& val){if (head == nullptr){return false;}else if (head->_val > val){_eraseR(head->_left, val);}else if (head->_val < val){_eraseR(head->_right, val);}else{//递归找到了Node* del = head;//三种情况//1.左子树为空if (head->_left == nullptr){head = head->_right;}//2.右子树为空else if(head->_right == nullptr){head = head->_left;}//3.左右子树都不为空else{//找LeftMaxNode* LeftMax = head->_left;while (LeftMax->_right){LeftMax = LeftMax->_right;}//交换swap(head->_val, LeftMax->_val);//递归删除return _eraseR(head->_left, val);}delete del;return true;}}Node* CopyTree(Node* head){if (head == nullptr){return nullptr;}Node* newhead = new Node(head->_val);newhead->_left = CopyTree(head->_left);newhead->_right = CopyTree(head->_right);return newhead;}};

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

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

相关文章

STM32CUBEMX_创建时间片轮询架构的软件框架

STM32CUBEMX_创建时间片轮询架构的软件框架 说明&#xff1a; 1、这种架构避免在更新STM32CUBEMX配置后把用户代码清除掉 2、利用这种时间片的架构可以使得代码架构清晰易于维护 创建步骤&#xff1a; 1、使用STM32CUBEMX创建基础工程 2、新建用户代码目录 3、构建基础的代码框…

机器视觉工程,如何快速摸清即将面试公司的基本情况

1.公司背景调查 企业查&#xff0c;天眼查&#xff0c;对一家公司的股东信息&#xff0c;知识产权&#xff0c;经营范围&#xff0c;是否有诉讼&#xff0c;经营范围等等信息&#xff0c;以及网上对其的整体评价&#xff0c;薪资整体水平等等。 2.公司官方网站 有些公司的网…

MySQL表的增删查改以及基本查询样例

文章目录 表的增删查改创建表插入单行全列数据插入多行指定列数据插入失败则更新替换 select全列查询指定列查询查询字段为表达式为查询结果指定别名查询结果去重 where数学小于60的英语在70到100之间的名字为王开头的总分在 200 分以下的语文成绩 > 80 并且不姓王的 结果排…

软件UI工程师工作的岗位职责(合集)

软件UI工程师工作的岗位职责1 职责&#xff1a; 1.负责产品的UI视觉设计(手机软件界面 网站界面 图标设计产品广告及 企业文化的创意设计等); 2.负责公司各种客户端软件客户端的UE/UI界面及相关图标制作; 3.设定产品界面的整体视觉风格; 4.参与产品规划构思和创意过程&…

Matlab信号处理1:模拟去除信号噪声

由于工作内容涉及信号系统、信号处理相关知识&#xff0c;本人本硕均为计算机相关专业&#xff0c;专业、研究方向均未涉及信号相关知识&#xff0c;因此需进行系统地学习。之前已将《信号与系统》快速过了一遍&#xff0c;但感觉较抽象且理解较浅显。在此系统地学习如何使用Ma…

食品化妆品核辐射检测

GB 14883.3-2016 GB 14883.3-2016 这次核污水时间&#xff0c;对我们的生活影响是比较大&#xff0c;尤其是未来几十年几百年的伤害最深&#xff0c;因为这是不可磨灭的伤害&#xff0c;无法去除&#xff01; 所以我要抵制日本任何的食物&#xff0c;尤其是海鲜食品&#xff…

前端如何将后台数组进行等分切割

前端如何切割数组 目标&#xff1a;前端需要做轮播&#xff0c;一屏展示12个&#xff0c;后端返回的数组需要进行切割&#xff0c;将数据以12为一组进行分割 环境&#xff1a;vue3tselement plus 代码如下&#xff1a; function divideArrayIntoEqualParts(array, chunkSiz…

docker使用(二)提交到dockerhub springboot制作镜像

docker使用&#xff08;二&#xff09; dockerhub创建账号创建存储库成功&#xff01;开始推送获取image名 提交成功SpringBoot项目制作Dockerfile镜像部署打jar包 dockerhub创建账号 &#xff08;自认为可以理解为github一类的东西&#xff09; 单击创建存储库按钮。 设定存…

Linux以系统服务的方式启动Kafka(其他服务同理)

最终效果&#xff1a; 先回顾命令行的启动方式&#xff1a; kafka的启动 进入kafka的安装目录 1、首先启动zookeeper服务&#xff1a; bin/zookeeper-server-start.sh config/zookeeper.properties2、再启动kafka bin/kafka-server-start.sh config/server.properties &…

数学建模--最短路径算法的Python实现

目录 1.算法流程简介 2.算法核心代码 3.算法效果展示 1.算法流程简介 #最短路径算法 #针对有向图的最短路径问题,我们有很多的算法能解决. """ 目前主流算法如下所示: Dijkstra算法:Dijkstra算法是一种单源最短路径算法,用于计算从起点到其它所有节点的最短…

13 mysql date/time/datetime/year 的数据存储

前言 这里主要是 由于之前的一个 datetime 存储的时间 导致的问题的衍生出来的探究 探究的主要内容为 int 类类型的存储, 浮点类类型的存储, char 类类型的存储, blob 类类型的存储, enum/json/set/bit 类类型的存储 本文主要 的相关内容是 datetime/date/time/year 类类型…

systemverilog运行的时候调用系统函数运行python等

systemverilog 运行的时候使用系统函数 使用场景&#xff0c;在仿真过程中&#xff0c;需要外部环境准备仿真参数&#xff0c;或者调整仿真参数的时候 创建一个python文件 print("123")创建一个sv文件 module dut ;initial begin$system("python 123.py"…