从零开学C++:二叉搜索树

news2024/9/29 13:03:10

引言:在本篇博客当中,我们会将关于二叉树的进阶结构——二叉搜索树,强大的搜索效率让它在数据结构当中变得十分重要,让我们一起来进行学习吧!

更多有关C++的知识详解可前往个人主页:计信猫

一,二叉搜索树的概念

        二叉搜索树的概念其实很简单,首先它一定满足成为一颗二叉树的基本条件,其次值比根节点小的储存在左子树,值比根节点大的储存在右子树,同时它的左右子树也为二叉搜索树。如图就是一颗简单的二叉搜索树

二,二叉搜索树的创建

        既然我们想创建一颗二叉搜索树,那么首先我们就应该创建一个二叉搜索树节点结构体(我们称为Node),如下代码所示:

template<class k>
class Node
{
public:
	Node(const k& key)
		:_left(nullptr)
		, _right(nullptr)
		, _key(key)
	{}
	Node* _left;
	Node* _right;
	k _key;//key为所储存的值
};

        此后我们还应该创建一个结构体专门用于二叉搜索树的遍历,数据操作,代码如下:

template<class k>
class BSTree
{
public:
	using Node = Node<k>;
    Node* _root = nullptr;
};

三,二叉搜索树的数据操作函数

1,插入数据

        在二叉搜索树中,我们想插入一个值其实就非常简单了,我们分为两种情况:

        情况一:当二叉搜索树为一个空树时,那么我们就直接创建一个节点并且将这个节点赋值给_root即可。

        情况二:即不为空树时,那么我们只需要根据二叉搜索树的规则遍历到二叉树的根节点,再把数据插入即可。

        所以我们的代码如下:

//插入数据
bool insert(const k& key)
{
	//情况一:根节点为空
	if (_root == nullptr)
	{
		_root = new Node(key);
		return true;
	}
	//情况二:根节点不为空
	else
	{
		//比根节点大的放左边,比根节点小的放右边
		Node* cur = _root;
		Node* parent = nullptr;
		//cur遍历到根节点
		while (cur)
		{
			if (key > cur->_key)
			{
				parent = cur;
				cur = cur->_right;
			}
			else if (key < cur->_key)
			{
				parent = cur;
				cur = cur->_left;
			}
			else
			{
				return false;
			}
		}
		cur = new Node(key);
		//比父节点小就插入左边,反之则插入右边
		if (parent->_key > key)
		{
			parent->_left = cur;
		}
		else
		{
			parent->_right = cur;
		}
		return true;
	}

 2,查找数据

        该函数的作用是查找二叉搜索树中是否存在值key,如果在遍历的过程中找到了值key,那么就返回true,若未找到值key,就返回false。那么代码如下:

//查找数据
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//相等就返回true
		{
			return true;
		}
	}
	return false;
}

 3,删除数据

        删除数据函数在本篇博客中就相对复杂,但没事,我将分情况来进行一一地讲解。

(1)删除的节点左右子树都为空

        这种情况就非常简单,删除这种叶子节点(cur)我们只需要将其父节点的左右指针指向空,然后delete掉这个叶子节即可,如下图所示:

        而该种情况可以被我们直接归类为情况(2)或情况(3) 。

(2)删除的节点左子树不为空,右子树为空

        当我们遇到这种情况的时候,我们就可以将其父节点(parent)与这个节点(cur)的左孩子相连,但连接的时候我们同时需要判断这个节点与父节点的左右关系如果被删除节点在父节点的左边,那么我们就应该将该节点的左子树插入到父节点的左边,反之我们则插入父节点的右边。如下图所示:

        可一旦当我们遇到如下图的情况就要进行特殊处理:

        其实处理办法也很简单,我们只需要根节点的左孩子赋值给_root,然后再删除cur节点即可。所以该情况下处理的代码如下:

else if (cur->_right == nullptr)//cur的右边为空
{
	if (cur == _root)//特殊情况
	{
		_root = cur->_left;
	}
	else
	{
		if (parent->_left == cur)//左孩子被删除
		{
			parent->_left = cur->_left;
		}
		else//右孩子被删除
		{
			parent->_right = cur->_left;
		}
	}
	delete cur;
	return true;
}

(3)删除的节点左子树为空,右子树不为空

        那么这种情况其实就可以直接类比到情况(2)了,此时我们就可以直接展示代码:

if (cur->_left == nullptr)//cur的左边为空
{
	if (cur == _root)//特殊情况
	{
		_root = cur->_right;
	}
	else
	{
		if (parent->_left == cur)//左孩子被删除
		{
			parent->_left = cur->_right;
		}
		else//右孩子被删除
		{
			parent->_right = cur->_right;
		}
	}
	delete cur;
	return true;
}

(4)删除的节点左子树和右子树都不为空

        这种情况是最麻烦的一种,但是不用担心,静下心来慢慢理解,你会发现易如反掌。那让我们以下图为例子:

        那么解决这种问题,我们就会用到一种方法,叫做替换法替换法的含义是找到左子树的最右节点或者右子树的最左节点,来替换掉要删除的节点,再删除需要被删除的节点。语言听着很晦涩,那么我们以图来说明!

        这样,一个节点就成功被我们删除了!但是要注意,连接节点的时候还是要进行判断,若被删除的节点是在其父节点的左边,那么替换的节点也必须被连接在父节点的左边,同理,右边也是一样的。所以我们的代码如下:

//删除数据
bool erase(const k& key)
{
	Node* cur = _root;
	Node* parent = nullptr;
	//使用cur先遍历到要删除的节点的位置
	while (cur)
	{
		if (key > cur->_key)
		{
			parent = cur;
			cur = cur->_right;
		}
		else if (key < cur->_key)
		{
			parent = cur;
			cur = cur->_left;
		}
		else
		{
			//相等,进行删除操作
			if (cur->_left == nullptr)//cur的左边为空
			{
				if (cur == _root)
				{
					_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)//cur的右边为空
			{
				if (cur == _root)
				{
					_root = cur->_left;
				}
				else
				{
					if (parent->_left == cur)//左孩子被删除
					{
						parent->_left = cur->_left;
					}
					else//右孩子被删除
					{
						parent->_right = cur->_left;
					}
				}
				delete cur;
				return true;
			}
			else//左右均不为空,使用替换法删除:左子树的最大值或者右子树的最小值
			{
				Node* replace = cur->left;
				Node* replaceparent = cur;
				while (replace->_right)
				{
					replaceparent = replace;
					replace = replace->_right;
				}
				cur->_key = replace->_key;
				if (replaceparent->_left == replace)
				{
					replaceparent->_left = replace->_left;
				}
				else
				{
					replaceparent->_right = replace->_left;
				}
				delete replace;
				return true;
			}
		}
	}
	return false;
}

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

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

相关文章

Android开发版本更新和强制更新效果

Android开发版本更新和强制更新效果 版本更新基本每个app都有&#xff0c;这里加多个强制更新效果 一、思路&#xff1a; 用okhttp下载接口返回的apk下载地址&#xff0c;这样有进度条 二、效果图&#xff1a; Android开发教程实战案例源码分享-版本更新和强制更新效果 三、…

建筑师设计师必备的14个AI工具

从制作复杂的设计到可视化突破性的建筑创新&#xff0c;建筑领域一直与技术紧密交织。随着我们深入数字时代&#xff0c;建筑师和设计师利用尖端人工智能 (AI) 工具的力量来革新他们的工艺也就不足为奇了。但是&#xff0c;随着市场上 AI 工具的大量出现&#xff0c;哪些工具真…

Pymsql 插入数据时报错 Unkown column xxxx in field list

如图 从文字来看&#xff0c;它是说我们表里没有“247dxxxxxxx”这个字段&#xff0c;但问题是我建表的时候本来就没建这个字段&#xff0c;这一串字符是我要插入到“id”这个字段里的内容&#xff0c;它怎么就把它当成字段了呢&#xff1f; 后来发现是在传入参数的时候&#…

Java 发布jar包到maven中央仓库(2024年9月保姆级教程)

文章目录 前言一、账号准备1. 注册登录账号2. 新建命名空间3. 验证命名空间4. 生成令牌5. 为 maven 设置令牌二、GPG准备1. 下载GPG2. 发布证书2.1 新建证书2.2 发布证书到服务器2.3 验证发布三、发布jar包到中央仓库1. 编辑项目pom文件2. 打包上传3. 发布jar包4. 搜索我们的ja…

分片上传和断点续传

今天介绍两个概念&#xff1a; 1、分片上传 分片上传&#xff0c;就是将所要上传的文件&#xff0c;按照一定的大小&#xff0c;将整个文件分隔成多个数据块来进行分别上传&#xff0c;上传完之后再由服务端对所有上传的文件进行汇总整合成原始的文件。 2、断点续传 断点续…

C语言课程设计题目三:图书管理系统设计

题目三&#xff1a;图书管理系统设计 图书管理信息包括&#xff1a;图书名称、图书编号、单价、作者、存在状态、借书人姓名、性别、学号等。 主要功能&#xff1a; 新进图书基本信息的输入。图书基本信息的查询。对撤销图书信息的删除。为借书人办理注册。办理借书手续。办理…

数据流处理技术与Flink框架

一数据流 数据流定义&#xff1a; 数据流&#xff08;Data Stream&#xff09;是指数据以连续不断的方式到达和处理的序列。在现实世界中&#xff0c;许多数据来源都是以流的形式存在&#xff0c;比如&#xff1a; 1. 用户行为&#xff1a;用户在网站上的点击流、移动应用中…

微软 Win11 RP 226x1.4247(KB5043145)预览版发布!

系统之家于9月25日发出最新报道&#xff0c;微软面向Release Preview频道的用户发布了Win11的KB5043145更新。系统更新后版本号提升为22621.4247和22631.4247。此次更新新增多项功能&#xff0c;例如用户播放媒体时&#xff0c;媒体控件会显示在锁屏中央的下部。以下跟随小编看…

LeetCode2207解题思路

题目描述 字符串中最多数目的子序列 解题思路&#xff1a; 题目要求我们找到在 text 中 找到最多可组成 pattern 的字符串个数&#xff0c;并且允许在 text 的任意位置插入 pattern 中一个字符&#xff0c;也就是说我们只需要考虑 text 中的 pattern 含有的字符即可。例如示例…

【React】组件基础使用

1. react组件 在react中&#xff0c;组件就是首字母大写的函数&#xff0c;内部存放了组件的逻辑、UI&#xff0c;渲染组件只需要把组件当成标签书写。 使用组件有两种方式&#xff1a;自闭和 、成对标签 function App() {// 定义组件function Component() {return <div&…

从入门到入土:计算机视觉CV学习路线图

在当今这个被数据和图像淹没的世界&#xff0c;计算机视觉&#xff08;CV&#xff09;正如一位聪明绝顶的魔术师&#xff0c;能够从无数的图像中提取出有意义的信息。对于那些初入这个领域的新人&#xff0c;学习计算机视觉既是一场冒险&#xff0c;也是一场盛宴。让我作为一位…

安科瑞诚邀您参加2024年CDCE国际数据中心及云计算展

展会邀请 安科瑞&#xff08;Acrel&#xff09;诚挚邀请您和您的公司代表参观我们在2024年CDCE国际数据中心及云计算展上的展位。 安科瑞&#xff08;Acrel&#xff09;是一家集研发、生产、销售和服务于一体的企业&#xff0c;成立于2003年并于2012年在创业板上市&#xff0…

探索机器人快换盘技术的未来之路:智能化与协作的革新

在当今快速发展的科技时代&#xff0c;机器人已成为众多领域不可或缺的得力助手。其中&#xff0c;机器人快换盘技术作为提升机器人灵活性和应用广度的重要技术&#xff0c;正经历着前所未有的变革与创新。下面请随我们一起深入探讨这一技术的未来发展趋势。 一、人工智能&…

建投数据获得安防工程企业设计施工维护能力证书(壹级)

近日&#xff0c;经中国安全防范产品行业协会审核&#xff0c;建投数据顺利获得安防工程企业设计施工维护能力证书&#xff08;壹级&#xff09;。 安防工程企业设计施工维护资质是对企业安防工程设计、施工、维护等领域专业能力的综合认证&#xff0c;是衡量企业规模、工程业绩…

阿里云百炼SFT微调实践

1. 场景识别 用户进行SFT前需要对应用场景进行识别和分析&#xff0c;一般进行模型微调的诉求是希望提升对应业务场景的能力&#xff0c;用户需要明确哪些能力是需要进行重点提升的。 场景划分上来讲&#xff0c;以垂类场景进行划分可分为教育、医疗、金融、法律、电商、旅游、…

IP地址的打卡路径是什么?

众多周知&#xff0c;IP地址使我们浏览网站的“必需品”&#xff0c;他会在我们进行网络活动时起到通关文牒一般的作用。那么&#xff0c;放我们进行网络活动时&#xff0c;我们的“通关文牒”上面会在哪些地点留下痕迹&#xff0c;IP地址的流转路径是什么&#xff1f; 第一关…

2024国庆节有哪些必囤的好物产品?一文了解那些入手不亏的国庆好物

国庆假期即将来临。对于追求品质生活的朋友们来说&#xff0c;这无疑是一个不容错过的购物机会。那么&#xff0c;在这个国庆&#xff0c;哪些好物值得你重点关注呢&#xff1f;我特地整理了一份推荐清单&#xff0c;这些产品不仅经过我的亲身体验&#xff0c;更以其卓越的实用…

建投数据自主研发相关系统获得欧拉操作系统及华为鲲鹏技术认证书

近日&#xff0c;经欧拉生态创新中心和华为技术有限公司测评&#xff0c;建投数据自主研发的投资项目管理系统、全面风险管理信息系统、商业不动产业务系统&#xff0c;完成了基于欧拉操作系统openEuler 22.03、华为鲲鹏Kunpeng 920&#xff08;Taisha 200&#xff09;的兼容性…

快速创建第一个Spring Boot 项目

一、介绍 Spring Boot 是一个开源的 Java 基础框架&#xff0c;它基于 Spring 框架&#xff0c;用于创建独立、生产级别的基于 Spring 的应用程序&#xff0c;你可以“跑起来”&#xff08;run&#xff09;你的 Spring 应用程序。Spring Boot 让基于 Spring 的应用开发变得更容…

Spring Boot 3.x 配置 Spring Doc以及导入postman带图详解

一、pom.xml配置 <!-- API⽂档⽣成&#xff0c;基于swagger3 --><dependency><groupId>org.springdoc</groupId><artifactId>springdoc-openapi-starter-webmvc-ui</artifactId><version>2.0.2</version></dependency>…