【C++】————搜索二叉树

news2025/1/11 10:02:34

 9efbcbc3d25747719da38c01b3fa9b4f.gif

                                                      作者主页:     作者主页

                                                      本篇博客专栏:C++

                                                      创作时间 :2024年7月22日

9efbcbc3d25747719da38c01b3fa9b4f.gif

什么是二叉搜索树?

二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树:

  • 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
  • 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
  • 它的左右子树也分别为二叉搜索树

如何建立一颗二叉搜索树?

建立一颗二叉搜索树一般有下面几个步骤,首先我们要建立一颗空树,然后不断的去插入节点,前面我们说过对于一颗二叉搜索树,小于节点对应的值放在左边,大于节点对应的值放在右边。

想要插入一个节点,我们就要从根节点开始比较,如何小于就往右边走,大于就往左边走。

想要查找一个节点,我们也是从根节点开始,找到合适的位置之后插入。

二叉搜索树的实现

BST树的基本结构:

节点结构:

template<class K>
struct BSTNode
{
	K _key;
	BSTNode<K>* _left;
	BSTNode<K>* _right;



	BSTNode(const K& key)
		:_key(key)
		,_left(nullptr)
		,_right(nullptr)
	{}

};

这就是一个二叉搜索树对应的节点的基本结构,我们是基于链表来实现他的,包括对应的值,还有左子树,右子树。

查找对应的值是否存在:

查找对应的值我们还是那个思路,就是比对应的节点小就往左边走,大就往右边走。

bool Find(const K& key)
{
	Node* cur = _root;
	while (cur)
	{
		if (cur->_key < key)
		{
			cur = cur->_right;
		}
		else if (cur->_key > key)
		{
			cur = cur->_left;
		}
		else if (cur->_key == key)
		{
			return true;
		}
	}
	return false;
}

插入一个值:

插入也是比较简单的,就是一直往下找,当下一个为空时,就直接插入。

这里还要注意如果已经存在这个值了,就会插入失败,还有最后还要判断一下是插入在左边还是右边。

bool Insert(const K& key)
{
	if (_root == nullptr)
	{
		_root = new Node(key);
		return true;
	}

	Node* parent = nullptr;
	Node* cur = _root;
	while (cur)
	{
		if (cur->_key < key)
		{
			parent = cur;
			cur = cur->_right;
		}
		else if (cur->_key > key)
		{
			parent = cur;
			cur = cur->_left;
		}
		else return false;
	}
	cur = new Node(key);
	if (parent->_key < key)
	{
		parent->_right = cur;
	}
	else if (parent->_key > key)
	{
		parent->_left = cur;
	}

	return true;
}

中序遍历:

我们在看到中序遍历之后其实也能初步的明白搜索二叉树的一个作用,那就是排序,因为中序遍历的结果就是一个升序的结果。

中序遍历的结果我们也已经在前面的二叉树章节中讲清楚,这里我们不再多说。

void _Inorder(Node* root)
{
	if (root == nullptr)
	{
		return;
	}

	_Inorder(root->_left);
	cout << root->_key << " ";
	_Inorder(root->_right);
}

删除:

最后我们来说一下删除,这个是最麻烦的一个,因为删除可以分为多种情况,比如如果要删除的这个节点没有孩子或者只有一个孩子,那么我们直接让这个节点的父亲指向另一个对应的节点。比如他是左孩子,那就指向右孩子,相反也是如此。

但如果是中间的某个节点怎么办,删除这个节点之后我们后面要如何去调整呢,这里我们就要找一个替代节点来代替要删除的这个节点,那我们该找谁呢?

我们其实可以选择这两个:左子树的最大节点,右子树的最小节点。仔细观察就可以发现,这两个节点都是符合逻辑的。这里我们找的是右子树的最小节点。

bool erase(K& key)
{
	Node* cur = _root;
	Node* parent = nullptr;
	while (cur)
	{
		if (cur->_key < key)
		{
			parent = cur;
			cur = cur->_right;
		}
		else if (cur->_key > key)
		{
			parent = cur;
			cur = cur->_left;
		}
		else
		{
			//删除
			//0 1个孩子
			if (cur->_left == nullptr)
			{
				if (parent == nullptr)//如果一棵树只有两个节点,然后parent此时可能就是nullptr,那么就要进行这一步,直接让_root指向cur的不是空的那个节点
				{
					_root = cur->_right;
				}
				else
				{
					if (parent->_left == cur)
					{
						parent->_left = cur->_right;
					}
					else
						parent->_right = cur->_right;
				}
				

				delete cur;
				return true;
			}
			else if (cur->_right == nullptr)
			{
				if (parent==nullptr)
				{
					parent = cur->_left;
				}
				else
				{
					if (parent->_left == cur)
					{
						parent->_left = cur->_left;
					}
					else
						parent->_right = cur->_left;
				}
				

				delete cur;
				return true;
			}
			//两个孩子
			else
			{
			    //找右子树最小节点
				Node* rightMin = cur->_right;
				Node* rightMinP = cur;//防止未进入while循环,所以定义成cur
				while (rightMin->_left)
				{
					rightMinP = rightMin;
					rightMin = rightMin->_left;
				}

				cur->_key = rightMin->_key;

				//这里要看右边的情况
				if (rightMinP->_left == rightMin)//如果右边的rightMin的左边还有节点
				{
					rightMinP->_left = rightMin->_right;
				}
				else
					rightMinP->_right = rightMin->_right;//如果右边的rightMin的左边为空了
				
				delete rightMin;
				return true;
				
			}
		}
		
	}
}

二叉搜索树的应用

1. K模型 :

K模型即只有key作为关键码,结构中只需要存储Key即可,关键码即为需要搜索到的值。
比如:给一个单词word,判断该单词是否拼写正确,具体方式如下:
以词库中所有单词集合中的每个单词作为key,构建一棵二叉搜索树
在二叉搜索树中检索该单词是否存在,存在则拼写正确,不存在则拼写错误。


2. KV模型 :

每一个关键码key,都有与之对应的值Value,即<Key, Value>的键值对。该种方
式在现实生活中非常常见:
比如英汉词典就是英文与中文的对应关系,通过英文可以快速找到与其对应的中文,英文单词与其对应的中文<word, chinese>就构成一种键值对;
再比如统计单词次数,统计成功后,给定单词就可快速找到其出现的次数,单词与其出 现次数就是<word, count>就构成一种键值对。

 二叉搜索树的性能分析


插入和删除操作都必须先查找,查找效率代表了二叉搜索树中各个操作的性能。

对有n个结点的二叉搜索树,若每个元素查找的概率相等,则二叉搜索树平均查找长度是结点在二叉搜索树的深度的函数,即结点越深,则比较次数越多。

但对于同一个关键码集合,如果各关键码插入的次序不同,可能得到不同结构的二叉搜索树:

最优情况下:二叉搜索树为完全二叉树(或者接近完全二叉树),其平均比较次数为:log(N)

最差情况下:二叉搜索树退化为单支树(或者类似单支),其平均比较次数为 N

 如果退化为单支树,二叉搜索树的性能就失去了。那能否进行改进?无论按照什么次序插入关键码,都能达到最优?这就需要AVL树和红黑树了。

最后:

十分感谢你可以耐着性子把它读完和我可以坚持写到这里,送几句话,对你,也对我:

1.一个冷知识:
屏蔽力是一个人最顶级的能力,任何消耗你的人和事,多看一眼都是你的不对。

2.你不用变得很外向,内向挺好的,但需要你发言的时候,一定要勇敢。
正所谓:君子可内敛不可懦弱,面不公可起而论之。

3.成年人的世界,只筛选,不教育。

4.自律不是6点起床,7点准时学习,而是不管别人怎么说怎么看,你也会坚持去做,绝不打乱自己的节奏,是一种自我的恒心。

5.你开始炫耀自己,往往都是灾难的开始,就像老子在《道德经》里写到:光而不耀,静水流深。

最后如果觉得我写的还不错,请不要忘记点赞✌,收藏✌,加关注✌哦(。・ω・。)

愿我们一起加油,奔向更美好的未来,愿我们从懵懵懂懂的一枚菜鸟逐渐成为大佬。加油,为自己点赞!

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

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

相关文章

大模型学习笔记 - LLM指令微调

LLM 指令微调 LLM 指令微调 0. 概览1. 指令数据的构建 1.1 基于现有NLP任务数据集构建1.2 基于日常对话数据构建1.3 基于合成数据构建1.4 指令数据构建的提升方法 2. 指令微调的策略 2.1 优化设置2.2 数据组织策略 3. 参数高效的模型微调 3.1 低秩适配微调方法3.2 其他高效微调…

【跨链机制】哈希锁定原理

随着区块链多年来的发展&#xff0c;在区块链生态中已经形成了不同特性的区块链网络&#xff0c;这些网络之间存在着一定的隔离和孤立性。为了打破这种局面&#xff0c;跨链技术应运而生&#xff0c;促进了区块链间的数据流通和价值交换。目前&#xff0c;主流的跨链机制包括公…

电路学习——经典运放电路之滞回比较器(施密特触发器)(2024.07.18)

参考链接1: 电子设计教程29&#xff1a;滞回比较器&#xff08;施密特触发器&#xff09; 参考链接2: 滞回比较器电路详细分析 参考链接3: 比较器精髓&#xff1a;施密特触发器&#xff0c;正反馈的妙用 参考链接4: 比较器反馈电阻选多大&#xff1f;理解滞后效应&#xff0c;轻…

Kafka之存储设计

文章目录 1. 分区和副本的存储结构1. 分区和副本的分布2. 存储目录结构3. 文件描述 2. 相关配置3. 数据文件类型4. 数据定位原理LogSegment 类UnifiedLog 类 5. 副本数据同步HW水位线LEO末端偏移量HW更新原理 6. 数据清除 1. 分区和副本的存储结构 在一个多 broker 的 Kafka 集…

如何学习Linux:糙快猛的大数据之路( 只讲大数据开发用到的)

引言 还记得第一次面对Linux命令行时的茫然吗&#xff1f;黑乎乎的终端&#xff0c;闪烁的光标&#xff0c;还有那些看起来像外星文的命令。 作为一个从0基础开始跨行到大数据领域的开发者&#xff0c;我深深体会到了学习Linux的重要性和挑战。今天&#xff0c;我想和大家分享…

谷粒商城实战-Vue学习过程中踩坑记录

一&#xff0c;自闭合的<script>标签 第一次使用Vue&#xff0c;按照步骤引入vue.js&#xff0c;创建div&#xff0c;创建Vue对象&#xff0c;但是未达预期效果。 插值表达式{{name}}没被替换为data对象中的属性值。 F12看了下网页源代码&#xff0c;发现创建Vue对象的…

计算机组成原理面试知识点总结1

#ウルトラマンゼット&#xff08;泽塔&#xff09; 1 计算机发展历程 1.1 计算机的硬件发展 电子管时代晶体管时代中小规模集成电路时代超大规模集成点电路时代 元件更新变化&#xff1a; 摩尔定律&#xff1a;18 个月晶体管翻一倍半导体存储器不断发展微处理器不断发展 1.2…

适合学生的护眼台灯哪个牌子最好?学生护眼台灯十大排名名单

适合学生的护眼台灯哪个牌子最好&#xff1f;作为一名当代的学生&#xff0c;经常会出现长时间用眼的情况&#xff0c;但是这种状况是难以改变的&#xff0c;我国的学习教育一直都在“内卷”&#xff0c;学生课业重&#xff0c;每日的夜间学习更是成了孩子的家常便饭&#xff0…

数据结构之字符串的最长公共子序列问题详解与示例(C,C++)

文章目录 1、最长公共子序列定义2、动态规划解法3、状态转移方程初始化构建最长公共子序列 4、C 和 C 实现示例C 语言实现C 语言实现 5、总结 字符串的最长公共子序列&#xff08;Longest Common Subsequence, LCS&#xff09;是计算机科学中的一个经典问题&#xff0c;属于动态…

08、Tomcat 部署及优化

8.1 Tomcat概述 8.1.1 Tomcat介绍 自从 JSP 发布之后,推出了各式各样的 JSP 引擎。Apache Group 在完成 GNUJSP1.0的开发以后&#xff0c;开始考虑在 SUN 的 JSWDK 基础上开发一个可以直接提供 Web 服务的 JSP服务器&#xff0c;当然同时也支持 Servlet, 这样 Tomcat 就诞生…

函数(递归)

递归&#xff1a;程序调用自身编程技巧称为递归。 在学习递归前需要粗略的了解一下内存&#xff0c;内存分为三类&#xff0c;分别是栈区、堆区和静态区。对于栈区来说&#xff0c;每调用一次函数都会为本次函数开辟一块空间&#xff0c;然而栈区也是有空间限制的&#xff0c;随…

GCN知识总结

关键点&#xff1a; 1.理解图结构的形式 2.如何使用邻接矩阵实现其图结构形式 3.GCN卷积是如何实现节点特征更新的 核心公式&#xff1a; 特征提取&#xff1a; 处理好的x 代表节点特征&#xff0c;然后*权重&#xff0c;再*邻接。 A尖换元后&#xff1a; forward函数 传播规则…

基于SpringBoot+Vue的篮球竞赛预约平台(带1w+文档)

基于SpringBootVue的篮球竞赛预约平台(带1w文档) 基于SpringBootVue的篮球竞赛预约平台(带1w文档) 本系统提供给管理员对首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;项目分类管理&#xff0c;竞赛项目管理&#xff0c;赛事预约管理&#xff0c;系统管理等诸多功…

C++中的模板函数和模板类

模板是 C 中的泛型编程的基础&#xff0c;编写与类型无关的通用代码&#xff0c;是代码复用的一种手段。 作为强类型语言&#xff0c;C 要求所有变量都具有特定类型&#xff0c;由程序员显式声明或编译器推导。 但是&#xff0c;许多数据结构和算法无论在哪种类型上操作&#x…

【Java开发实训】day05——数组常见算法

目录 一、数组翻转 1.1示例代码 1.2适用场景 二、冒泡排序 2.1示例代码 2.2适用场景 三、二分查找 3.1示例代码 3.2适用场景 &#x1f308;嗨&#xff01;我是Filotimo__&#x1f308;。很高兴与大家相识&#xff0c;希望我的博客能对你有所帮助。 &#x1f4a1;本文由Filotimo…

Elasticsearch中任务管理怎么做?

一个ES集群研发在清理数据时使用了delete_by_query&#xff0c;导致集群性能严重受影响&#xff0c;影响了正常的业务。为了快速恢复集群正常状态&#xff0c;考虑把还在进行的delete_by_query任务清除掉。 先查看当前集群的任务 GET _cat/tasks?v发现delete_by_query的任务…

Git笔记:(上传Git、Git获取文件版本、删除、统计)

目录 一、上传文件到github 1.1 配置用户名和邮箱 1.2 初始化本地仓库 1.3 添加项目目录下所有文件至本地仓库 1.4 使用如下命令加入注释提交 1.5 将本地仓库与远程仓库相连接 1.6 将本地仓库中的文件推送至指定的远程仓库中 二、git获取不同版本 2.1 git下载特定历史…

[MySQL]02 存储引擎与索引,锁机制,SQL优化

Mysql存储引擎 可插拔式存储引擎 索引是在存储引擎底层上实现的 inno DB MySQL默认存储引擎: inno DB高可靠性和高性能的存储引擎 DML操作遵循ACID模型支持事务行级锁,提高并发访问性能支持外键 约束,保证数据完整性和可靠性 MySAM MySAM是MySQL的早期引擎 特点: 不支持事…

【数据结构_C语言】归并排序—文件类型

文章目录 1.排序定义2. 代码实现 1.排序定义 内排序&#xff1a;数据量相对少一些&#xff0c;可以放到内存中排序。 外排序&#xff1a;数据量较大&#xff0c;内存中放不下&#xff0c;数据放到磁盘文件中&#xff0c;需要排序。 归并排序&#xff1a; 2. 代码实现 void…

基于CNN-BiLSTM的数据回归预测

代码原理 基于CNN-BiLSTM的数据回归预测是一种结合卷积神经网络&#xff08;CNN&#xff09;和双向长短期记忆网络&#xff08;BiLSTM&#xff09;的混合模型&#xff0c;用于处理和预测时间序列数据。以下是该方法的简单原理及流程&#xff1a; 原理 &#xff08;1&#xf…