【数据结构】(初阶):二叉搜索树

news2024/9/25 11:21:33

✨前言✨

🎓作者:【 教主 】

📜文章推荐:

☕博主水平有限,如有错误,恳请斧正。

📌机会总是留给有准备的人,越努力,越幸运!

💦导航助手💦

概念

接口实现

节点定义

插入元素

删除元素 

查找元素


概念

二叉搜索树又称为二叉排序树,有以下几个特征

  • 左子树的值都比根节点的值小
  • 右子树的值都比根节点的值大
  • 左右子树也是二叉搜索树
  • 中序遍历是升序
  • 一般不支持改变元素

cdfca70afdb384e2d7cdcc4378308b03.jpeg

接口实现

注意:以下为C++模板实现

节点定义

template<class K>
struct BSTreeNode
{
	BSTreeNode(const K& val = val())
	{
		_left = nullptr;
		_right = nullptr;
		_val = val;
	}
	BSTreeNode* _left;
	BSTreeNode* _right;
	K _val;
};

插入元素

非递归版本

bool Insert(const K& val)
		{
			if (_root == nullptr)
			{
				_root = new Node(val);
				return true;
			}
			Node* cur = _root;
			Node* parent = nullptr;
			while (cur)
			{
				if (val > cur->_val)
				{
					parent = cur;
					cur = cur->_right;
				}
				else if (val < cur->_val)
				{
					parent = cur;
					cur = cur->_left;
				}
				else
				{
					return false;
				}
			}

			Node* newNode = new Node(val);
			if (val > parent->_val)
				parent->_right = newNode;
			else
				parent->_left = newNode;
			return true;
		}

递归版本

InsertR()函数为公有,_InesertR()函数为私有 ,调用时直接调用InsertR()即可。

bool InsertR(const K& val)
		{
			return _InsertR(_root, val);
		}
bool _InsertR(Node*& root, const K& val)
		{
			if (root == nullptr)
			{
				root = new Node(val);
				return true;
			}

			if (val > root->_val)
				return _InsertR(root->_right, val);
			else if (val < root->_val)
				return _InsertR(root->_left, val);
			else
				return false;
		}

删除元素 

非递归版本

bool Erase(const K& val)
		{
			Node* cur = _root;
			Node* parent = nullptr;
			while (cur)
			{
				if (val > cur->_val)
				{
					parent = cur;
					cur = cur->_right;
				}
				else if (val < cur->_val)
				{
					parent = cur;
					cur = cur->_left;
				}
				else
				{
					if (cur == _root)
					{
						if (cur->_left == nullptr)
						{
							_root = _root->_right;
							delete cur;
							cur = nullptr;
							return true;
						}
						else if (cur->_right == nullptr)
						{
							_root = _root->_left;
							delete cur;
							cur = nullptr;
							return true;
						}
						else
						{
							Node* min = cur->_right;
							Node* minParent = cur;
							while (min->_left)
							{
								minParent = min;
								min = min->_left;
							}
							if (minParent == cur)
							{
								std::swap(minParent->_val, min->_val);
								minParent->_right = min->_right;
								delete min;
								min = nullptr;
								return true;
							}
							else
							{
								std::swap(cur->_val, min->_val);
								minParent->_left = min->_right;
								delete min;
								min = nullptr;
								return true;
							}
						}

					}
					else
					{
						if (cur->_left == nullptr)
						{
							if (parent->_left == cur)
								parent->_left = cur->_right;
							else
								parent->_right = cur->_right;
						}
						else if (cur->_right == nullptr)
						{
							if (parent->_left == cur)
								parent->_left = cur->_left;
							else
								parent->_right = cur->_left;
						}
						else
						{
							Node* min = cur->_right;
							Node* minParent = cur;
							while (min->_left)
							{
								minParent = min;
								min = min->_left;
							}
							if (minParent == cur)
							{
								std::swap(minParent->_val, min->_val);
								minParent->_right = min->_right;
								delete min;
								min = nullptr;
								return true;
							}
							else
							{
								std::swap(cur->_val, min->_val);
								minParent->_left = min->_right;
								delete min;
								min = nullptr;
								return true;
							}
						}
					}
					return true;
				}
			}
		}

递归版本

EraseR()为公有,_EraseR()为私有,调用时直接调用Erase()即可。 

bool EraseR(const K& val)
		{
			return _EraseR(_root, val);
		}
bool _EraseR(Node*& root, const K& val)
		{
			if (root == nullptr)
				return false;

			if (val > root->_val)
			{
				return _EraseR(root->_right, val);
			}
			else if (val < root->_val)
			{
				return _EraseR(root->_left, val);
			}
			else
			{
				Node* del = root;
				if (root->_left == nullptr)
				{
					root = root->_right;
					delete del;
					del = nullptr;
					return true;
				}
				else if (root->_right == nullptr)
				{
					root = root->_left;
					delete del;
					del = nullptr;
					return true;
				}
				else
				{
					Node* min = root->_right;
					Node* minParent = root;
					while (min->_left)
					{
						minParent = min;
						min = min->_left;
					}
					if (minParent == root)
					{
						std::swap(root->_val, min->_val);
						minParent->_right = min->_right;
						delete min;
						min = nullptr;
						return true;
					}
					std::swap(root->_val, min->_val);
					return _EraseR(root->_right, val);
				}
				
			}
		}

查找元素

非递归版本 

Node* Find(const K& val)
		{
			Node* cur = _root;
			while (cur)
			{
				if (val > cur->_val)
					cur = cur->_right;
				else if (val < cur->_val)
					cur = cur->_left;
				else
					return cur;
			}
			return nullptr;
		}

递归版本

FindR()为公有,_FindR()为私有,调用时直接调用FindR()即可。

Node* FindR(const K& val)
		{
			return _FindR(_root, val);
		}
Node* _FindR(Node*& root, const K& val)
		{
			if (root == nullptr)
				return nullptr;

			if (val > root->_val)
				return _FindR(root->_right, val);
			else if (val < root->_val)
				return _FindR(root->_left, val);
			else
				return root;
		}

欢迎关注,码字不易,希望多多点赞、收藏哦!抱拳了。

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

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

相关文章

Docker+Selenium Grid运行UI自动化

简介 使用Selenium Grid可以分布式运行UI自动化测试&#xff0c;可以同时启动多个不同的浏览器&#xff0c;也可以同时启动同一个浏览器的多个session。这里使用Docker Compose来同时启动不同浏览器的容器和Selenium Grid&#xff0c;只需一条命令就把自动化运行环境部署好了。…

verilog仿真技巧与bug集合

文章目录赋值语句想法一些建议时钟信号关于异步fifo写入数据时wp1&#xff0c;读出数据时rp1一些自己的bug关于操作符&关于if-else关于modelsim使用1.初学者不建议在设计文件中加入仿真语句&#xff1b; 2.初学者也不会在tb里使用类似always一样的设计。 对于1.因为把仿真…

国产RISC-V处理器“黑马”跑分曝光!超过多数国内主流高性能处理器!

来源企业投稿 2010年&#xff0c;开源、开放、精简的RISC-V架构诞生。虽然距今仅有12年&#xff0c;但RISC-V迎来了众多玩家的积极参与&#xff0c;其技术、生态、应用都快速发展。在许多秉持匠心的技术人员的耕耘下&#xff0c;RISC-V也早已从传统强项物联网走出&#xff0c;…

error: ‘uint8_t’,‘uint16_t’ ,‘uint32_t’ does not name a type

文章目录1、报错error: ‘uint8_t’,‘uint16_t’ ,‘uint32_t’ does not name a type2、解决办法3、uint8_t此类数据类型补充4、码字不易&#xff0c;点点赞1、报错error: ‘uint8_t’,‘uint16_t’ ,‘uint32_t’ does not name a type 在网络编程PING程序时遇到的小bug&am…

【BUUCTF】MISC(第二页wp)

文章目录被劫持的神秘礼物刷新过的图片[BJDCTF2020]认真你就输了[BJDCTF2020]藏藏藏被偷走的文件snake[GXYCTF2019]佛系青年[BJDCTF2020]你猜我是个啥秘密文件菜刀666[BJDCTF2020]just_a_rar[BJDCTF2020]鸡你太美[BJDCTF2020]一叶障目[SWPU2019]神奇的二维码梅花香之苦寒来[BJD…

day02-Java基础语法

day02 - Java基础语法 1 类型转换 在Java中&#xff0c;一些数据类型之间是可以相互转换的。分为两种情况&#xff1a;自动类型转换和强制类型转换。 1.1 隐式转换(理解) ​ 把一个表示数据范围小的数值或者变量赋值给另一个表示数据范围大的变量。这种转换方式是自动的&am…

外贸小白适合哪种邮箱?

除了一些企业指定的邮箱&#xff0c;大多数外贸人&#xff0c;尤其是小白的外贸人&#xff0c;都希望选择最合适的邮箱&#xff0c;赢在起跑线上。判断邮箱质量的两个主要因素是投递率和安全性。米贸搜的排列如下: 公共个人邮箱 此时常见的个人邮箱有国外的gmail、hotmail、雅…

2023 年软件开发人员可以学习的 10 个框架

开发者您好&#xff0c;我们现在处于 2023 年的第一周&#xff0c;你们中的许多人可能已经制定了 2023 年要学习什么的目标&#xff0c;但如果您还没有&#xff0c;那么您来对地方了。 早些时候&#xff0c;我分享了成为Java 开发人员、DevOps 工程师、React 开发人员和Web 开…

联合分析案全流程分析

联合分析(conjoint analysis)是一种研究消费者产品选择偏好情况的多元统计分析方法。比如消费者对于手机产品的偏好&#xff0c;对于电脑产品的偏好&#xff0c;也或者消费者对于汽车产品的偏好情况等。联合分析中涉及几个专业术语名词&#xff0c;分别如下所述&#xff1a; 联…

基于深度学习下的稳定学习究竟是什么?因果学习?迁移学习?之一

机器学习 | 稳定学习 | DGBR 深度学习 | 迁移学习 | 因果学习 众所周知&#xff0c;深度学习研究是机器学习领域中一个重要研究方向&#xff0c;主要采用数据分析、数据挖掘、高性能计算等技术&#xff0c;其对服务器的要求极其严格&#xff0c;传统的风冷散热方式已经不足以满…

C++---智能指针

目录 1. 为什么需要智能指针&#xff1f; 2. 内存泄漏 2.1 什么是内存泄漏&#xff0c;内存泄漏的危害 2.2 内存泄漏分类 2.4如何避免内存泄漏 3.智能指针的使用及原理 3.1 RAII 3.2 智能指针的原理 3.3 std::auto_ptr 3.4 std::unique_ptr 3.5 std::shared_ptr 3.6…

使用RMAN传输数据_创建可传输的表空间集(Creating Transportable Tablespace Sets)

传输数据比对相同的数据执行export/import或unload/load操作更快。因为对于用户定义的表空间&#xff0c;数据文件包含所有拷贝到目标位置的实际数据&#xff0c;你使用Data Pump只传输数据库对象的元数据到新数据库。 本章阐述如何使用RMAN通过还原备份来创建可传输的表空间集…

Dockfile是什么

目录 1. Dockfile是什么 2. Dockerfile的基本组成 2.1 FROM 2.2 MAINTAINER 2.3 RUN 2.4 COPY 2.5 ADD 2.6 EXPOSE 2.7 WORKDIR 2.8 ONBUILD 2.9 USER 2.10 VOLUME 2.11 CMD 2.12 ENTRYPOINT 3. dockerfile示例 3.1 准备 3.2 将该目录上传至linux 3.3 构建镜像…

2022年「博客之星」参赛博主:一个处女座的测试

我正在参加年度博客之星评选&#xff0c;请大家帮我投票打分&#xff0c;您的每一分都是对我的支持与鼓励。 五星必回&#xff0c;诚信互评&#xff0c;&#xff08;如果&#xff09;今日已满&#xff0c;明天必回&#xff0c;言出必行&#xff0c;感谢支持&#xff01; 我正在…

【深度探讨】数据存储进化论,区块链才是未来

发表时间&#xff1a;2022年5月23日 信息来源&#xff1a;bsvblockchain.org 需要一个适于处理这种日渐普及的资源的基础设施。 2022年2月&#xff0c;在沙特愿景2030区块链峰会上&#xff0c;BSV区块链协会创始主席Jimmy Nguyen就数据的价值这一话题发表了一场令人叹为观止的…

nodejs+vue+element+eachers构建开源项目大型连续剧(2)安装mysql数据库,在nodejs服务器中操作数据库数据

太长时间没更新了&#xff0c;然后&#xff0c;理由是什么呢&#xff1f;是因为阳了&#xff0c;真没想到&#xff0c;吃嘛嘛香的我忽然阳了&#xff0c;果然阳的初期症状就是嘴硬。然后&#xff0c;开始我们连续剧的第二集。 一、进行mysql的安装 学习第一步&#xff0c;从安…

[极客大挑战 2019]BuyFlag1(BUUCTF)

前言: 这篇文章还是是为了帮助一些 像我这样的菜鸟 找到简单的题解 题目描述 解题工具: 我爱用edit this cookie2和hackerbar&#xff0c; 当然也可以burpsuite和fiddler抓包 解题过程: 看到他说flag要100000000 MONEY&#xff0c; 还要是Cuits students&#xff0c; …

GCC嵌入汇编特性

前言 在C语言编程中&#xff0c;使用汇编指令有两种方式&#xff0c;一种是使用单独的汇编源文件&#xff0c;在最后编译的时候和其它C工程文件编译到一起&#xff0c;这种方式能够做到汇编函数和C函数的互相调用&#xff0c;但是如果希望在C语言中直接调用汇编表达式就不是那…

kibana在linux环境安装实战遇到的问题汇总

kibana在linux环境安装实战遇到的问题汇总&#xff1a; 1、找不到主节点的错误&#xff1a; savedobjects-service] Unable to connect to Elasticsearch. Error: [master_not_discovered_exception] null 原因是找不到es的主节点&#xff0c;意思是es没有配置主节点。 解决…

【Spring】Spring @Cacheable 官方学习及demo

文章目录前言Cacheable 的来源应用场景集成Redis的思路代码及验证后记前言 Spring 有很多声明式的编程风格&#xff0c;Transactional 是&#xff0c;Cacheable 也是。说起 Transactional&#xff0c;复杂的事务情况下&#xff0c;这个注解也有局限&#xff0c;需要用到编程式…