【C++】二叉搜索树的应用

news2024/11/16 2:53:56

前言

二叉搜索树本质也是二叉树,但因为其数据存储的特殊 — 左子树的值都更小,右子树的值都更大,所以在大部分情况下,查找更为高效。本篇博客将讲述二叉搜索树两个应用搜索的场景
那么话不多说,马上开始今天的学习。

在这里插入图片描述

文章目录

  • 前言
  • 一. Key的模型
  • 二. Key_Value的模型
  • 结束语

一. Key的模型

Key的模型本质其实是在不在的问题

  1. 比如:门禁系统。当我们在进出学校时,可能需要刷校园卡,那其实校园卡里面有芯片,跟门禁交互后,可以读取到你的信息,然后拿着这个信息,去数据库中查找,找到了,那就允许通行,找不到,就不允许通行。
  2. 再比如:车库系统。如果你有这个车库的停车位,那么你进出车库,车库的杆子直接就抬起,放行。但是如果你没有车位,那么你进入停车场依然抬杆,但是你出来时候,需要支付停车费才能抬杆。这也涉及到了信息的查找和匹配。

最普通的二叉搜索树就是Key的模型每个节点只存储一个数据,且其实际意义就是那个数据的意义
比如下面这个二叉搜索树,其意义就是整型数字的存储。
在这里插入图片描述
二叉搜索树Key模型的代码在【C++】二叉搜索树

二. Key_Value的模型

Key_Value的模型其实是映射关系Key不再单纯只有Key的意义,其还对应了一个Value
就像一把钥匙,他不仅是一把钥匙,他还有对应一个锁。我们的学号不仅是一串数字,他在学生信息管理系统中,还对应着我们的信息。

比如,我们要完成一个中英文互译的字典,就可以使用Key_Value模型,我们输入的Key是“sort”,对应的Value就是“排序”。

以下我们简单编写一下二叉搜索树的Key_Value模型的代码。其实基本框架和Key模型一样,只是类模板参数多了一个模板参数

//类模板,用于存储不同数据
	template<class K,class V>
	struct BinarySearchTree
	{
		BinarySearchTree<K,V>*_left;//左子树
		BinarySearchTree<K,V>*_right;//右子树
		K _key;//key值
		V _value;//value值

		//构造函数
		BinarySearchTree(const K&key,const V&value)
			:_left(nullptr)
			, _right(nullptr)
			, _key(key)
			,_value(value)
		{}

		~BinarySearchTree()
		{
			_left = nullptr;
			_right = nullptr;
		}
	};


	template<class K,class V>
	class BSTree
	{
		typedef BinarySearchTree<K,V> Node;
	public:
		//析构
		~BSTree()
		{
			Destroy(_root);
			_root = nullptr;
		}

		//插入
		bool Insert(const K&key,const V&value)
		{
			//头为空时单独处理
			if (_root == nullptr)
			{
				_root = new Node(key,value);
				return true;
			}

			//循环找插入的位置
			Node*cur = _root;
			//记录父节点,实现链接
			Node*parent = nullptr;
			while (cur)
			{
				parent = cur;
				if (key > cur->_key)
					cur = cur->_right;
				else if (key < cur->_key)
					cur = cur->_left;
				else
					//相等则返回假
					return false;
			}

			//找到了要插入的位置
			cur = new Node(key,value);
			//链接
			if (key > parent->_key)
				parent->_right = cur;
			else
				parent->_left = cur;

			return true;
		}

		//中序遍历
		//因为二叉搜索树的特点,中序打印出来就是升序

		//实现封装
		void InOrder()
		{
			_InOrder(_root);
			cout << endl;
		}

		//查找
		Node* Find(const K&key)
		{
			Node*cur = _root;
			//循环查找
			while (cur)
			{
				//比当前值小,则往左走
				if (key < cur->_key)
					cur = cur->_left;
				else if (key > cur->_key)//大则往右走
					cur = cur->_right;
				else//不然就是相等,相等就是找到了
					return cur;
			}

			//循环没返回说明没查到
			return nullptr;
		}

		//删除
		bool Erase(const K&key)
		{
			//分成两类
			//左或者右为空(包括叶子结点)
			//左右孩子都有

			//首先先找节点
			Node*cur = _root;
			//记录父亲节点
			Node*parent = nullptr;

			while (cur)
			{
				//parent = cur;
				if (key < cur->_key)
				{
					parent = cur;
					cur = cur->_left;
				}
				else if (key > cur->_key)
				{
					parent = cur;
					cur = cur->_right;
				}
				else
				{
					//找到了

					//分两种情况

					//左为空
					if (cur->_left == nullptr)
					{
						//还有可能删到根节点的一边为空(有点像歪脖子树)
						if (cur == _root)
							_root = cur->_right;
						else
						{
							//要判断父节点链接左还右
							if (parent->_left == cur)
								parent->_left = cur->_right;
							else
								parent->_right = cur->_right;
						}

						delete cur;
						cur = nullptr;

						return true;

					}  // 右为空
					else if (cur->_right == nullptr)
					{
						//还有可能删到根节点的一边为空(有点像歪脖子树)
						if (cur == _root)
							_root = cur->_left;
						else
						{
							//要判断父节点链接左还右
							if (parent->_left == cur)
								parent->_left = cur->_left;
							else
								parent->_right = cur->_left;
						}

						delete cur;
						cur = nullptr;

						return true;
					}
					else
					{
						//左右子树都不为空
						//找保姆
						//左子树的最大节点 or 右子树的最小节点  二者都可以
						//  最右节点             最左节点

						Node*pMinRight = cur;//右子树的最小节点的父节点
						Node*MinRight = cur->_right;//右子树的最小节点

						while (MinRight->_left)
						{
							pMinRight = MinRight;
							MinRight = MinRight->_left;
						}

						//直接赋值
						cur->_key = MinRight->_key;

						//判断父节点要链接左还是右
						if (pMinRight->_left == MinRight)
							pMinRight->_left = MinRight->_right;
						else
							pMinRight->_right = MinRight->_right;

						//删除MinRight,因为完成交换了
						delete MinRight;
						MinRight = nullptr;

						return true;
					}
				}
			}

			return false;
		}

	protected:

		//销毁二叉搜索树
		void Destroy(Node*root)
		{
			if (root == NULL)
				return;

			//先删除左右节点,再删除当前节点
			Destroy(root->_left);
			Destroy(root->_right);

			delete root;
			root = nullptr;
		}

		//因为要递归,所以要单独编写
		//注意此处不可以加缺省值_root,因为缺省值需要是常量
		void _InOrder(Node*root)
		{
			if (root == nullptr)
				return;

			_InOrder(root->_left);
			cout << root->_key << ":" << root->_value << endl;
			_InOrder(root->_right);
		}

	private:
		Node*_root = nullptr;//根节点
	};

我们以英汉互译为例子,测试一下
在这里插入图片描述
ctrl+z+回车可以正常结束这样的循环

结束语

感谢你的阅读

如果觉得本篇文章对你有所帮助的话,不妨点个赞支持一下博主,拜托啦,这对我真的很重要。
在这里插入图片描述

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

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

相关文章

linux运维必了解的日志文件系统

目录 一、inode与block1.1inode和block概述1.1.1inode和block的关系 1.2inode的内容1.2.1inode包含文件的元信息1.2.2linux文件系统的三个时间戳1.2.3目录文件结构 1.3inode的号码1.3.1 硬盘分区后的结构 1.4inode的大小1.5恢复误删除的xfs文件1.6EXT类型文件恢复误删除 二、分…

亿发软件:玩具批发行业需要怎样的进销存开单软件

中国玩具市场的发展潜力十分巨大&#xff0c;近五年来中国玩具行业的批发零售企业都保持着良好的发展态势。近年来&#xff0c;在数字化转型的时代浪潮下&#xff0c;玩具批发零售市场想实现进一步的高质量发展&#xff0c;充分满足客户多元化的供货需求&#xff0c;需要向数据…

Qt5 和 OpenCV4 计算机视觉项目:6~9

原文&#xff1a;Qt 5 and OpenCV 4 Computer Vision Projects 协议&#xff1a;CC BY-NC-SA 4.0 译者&#xff1a;飞龙 本文来自【ApacheCN 计算机视觉 译文集】&#xff0c;采用译后编辑&#xff08;MTPE&#xff09;流程来尽可能提升效率。 当别人说你没有底线的时候&#x…

OpenCV 图像处理学习手册:6~7

原文&#xff1a;Learning Image Processing with OpenCV 协议&#xff1a;CC BY-NC-SA 4.0 译者&#xff1a;飞龙 本文来自【ApacheCN 计算机视觉 译文集】&#xff0c;采用译后编辑&#xff08;MTPE&#xff09;流程来尽可能提升效率。 当别人说你没有底线的时候&#xff0c;…

javascript之数组

创建 有以下几种方式 1.构造函数 在使用构造函数时&#xff0c;可以不带new 创建空数组 let color new Array() 或者let color Array() 创建指定个数元素的数组 let color new Array(2) 或者let color Array(2) 创建指定元素的数组 let color new Array("bl…

atio函数和宏offset的介绍

目录 前言atoi函数宏offsetof总结 前言 本章带大家一起认识一些在我们C语言标准库中的函数 atoi函数 int atio(const char* str);头文件&#xff1a; #include<stdlib.h>参数&#xff1a; str指向常量字符串起始位置的指针 函数介绍&#xff1a; ①解析C语言字符串str,…

2023软件测试工程师必备技能?要卷,谁还不会了......

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 软件测试岗位是怎…

FPGA基于Tri Mode Ethernet MAC实现UDP通信 提供3套工程源码和技术支持

目录 1、前言2、我这里已有的UDP方案3、米联客UDP协议栈4、详细设计方案5、Tri Mode Ethernet MAC的使用6、vivado工程1详解7、vivado工程2详解8、vivado工程3详解9、上板调试验证并演示10、福利&#xff1a;工程代码的获取 1、前言 目前网上的fpga实现udp基本生态如下&#x…

Spring Security实战(五)—— 密码加密

一、密码加密的演进 MD5 (Message-Digest Algorithm 5) 和 SHA (Secure Hash Algorithm) 是两种常见的消息摘要算法&#xff0c;它们都被用于加密和数据完整性验证等领域。 MD5 是一种 128 位的哈希函数&#xff0c;常用于数据完整性校验和数字签名等方面。它将任意长度的信息…

WebServer项目(四)->(基于Proactor的c++)Web服务器简介及简单实现

基于Proactor的cWeb服务器项目 WebServer项目(四)-&#xff1e;(基于Proactor的c)Web服务器简介及简单实现1.Web Server&#xff08;网页服务器&#xff09;2.HTTP协议(应用层的协议)3.HTTP 请求报文格式4.HTTP响应报文格式5.HTTP请求方法6.HTTP状态码7.服务器编程基本框架8.两…

分布式搜索技术elasticsearch概念篇

文章目录 一、分布式搜索技术二、elasticsearch2.1 初识elasticsearch2.2 正向索引和倒排索引2.2.1 介绍2.2.2 优缺点 2.3 elasticsearch和mysql的对比 一、分布式搜索技术 分布式搜索技术是一种基于分布式计算的搜索引擎技术&#xff0c;它使用多台计算机协同工作来处理大规模…

ElementUI登陆表单中常用的标签属性

ElementUI官网 为登陆框添加一个边角弧度 <style> .className{/*设置div边边框角的弧度*/border-radius: 10px; } </style><el–input>标签常用属性 <!--使用prefix属性添加一个前缀图标--> <el-input prefix-icon"el-icon-user-solid"&g…

深度学习第J6周:ResNeXt-50实战解析

目录 一、模型结构介绍 二、前期准备 三、模型 三、训练运行 3.1训练 3.2指定图片进行预测 &#x1f368; 本文为[&#x1f517;365天深度学习训练营]内部限免文章&#xff08;版权归 *K同学啊* 所有&#xff09; &#x1f356; 作者&#xff1a;[K同学啊] &#x1f4cc; …

大数据技术之集群数据迁移

在大数据集群数据迁移的项目中涉及到很多技术细节&#xff0c;本博客记录了迁移的大致的操作步骤。 迁移借用Hadoop自带的插件&#xff1a;distcp。 一、Hadoop集群数据迁移 **DistCp&#xff08;分布式拷贝&#xff09;**是用于大规模集群内部和集群之间拷贝的工具。它使用M…

Meson构建系统的使用

一、前言 Meson 是用于自动化构建的自由软件&#xff0c;使用Python语言编写&#xff0c;在 Apache 许可证 2.0版本下发布&#xff0c;主要目标是为了让开发者节约用于配置构建系统的时间。 特点如下&#xff1a; 多平台支持&#xff0c;包括 GNU/Linux、Windows、MacOS、GCC、…

A_A01_008 STM32F103系列标准库移植经验分享

A_A01_008 STM32F103系列标准库移植经验分享 一、所需材料二、移植步骤三、注意事项四、参考资料与友情链接 一、所需材料 1.MDK开发环境 此处版本V5.15 2.相关启动文件 此处用野火点灯例程 因为启动文件完整 方便更换 其它工程没有的可以直接复制这些启动文件过去 3.相关开…

Java版工程管理系统源代码-软件自主研发,工程行业适用

Java版工程项目管理系统 Spring CloudSpring BootMybatisVueElementUI前后端分离 功能清单如下&#xff1a; 首页 工作台&#xff1a;待办工作、消息通知、预警信息&#xff0c;点击可进入相应的列表 项目进度图表&#xff1a;选择&#xff08;总体或单个&#xff09;项目显示…

8年测开年薪30W,为什么从开发转型为测试?谈谈这些年的心路历程……

谈谈我的以前&#xff0c;从毕业以来从事过两个多月的Oracle开发后转型为软件测试&#xff0c;到现在已近过去8年成长为一个测试开发工程师&#xff0c;总结一下之间的心路历程&#xff0c;希望能给徘徊在开发和测试之前的同学一点小小参考。 一、测试之路伏笔 上学偷懒&#…

EGO-Link FPGA智慧教育社区介绍:用 leetcode 的方式练习 verilog 语言

文章目录 介绍FPGA 语法例1&#xff1a;P1203 1输入1输出例2&#xff1a;P1204 3输入4输出例3&#xff1a;P1207 P1208 P1205 与或非门例4&#xff1a;P1200 半加器例5&#xff1a;P1201 4位二进制转余3循环码例6&#xff1a;P1215 2选1多路选择器例7&#xff1a;P1236 D触发器…

【C语言】浅涉结构体(声明、定义、类型、定义及初始化、成员访问及传参)

简单不先于复杂&#xff0c;而是在复杂之后。 目录 1. 结构体的声明 1.1 结构体的基础知识 1.2 结构的声明 1.3 结构成员的类型 1.4 结构体变量的定义和初始化 2. 结构体成员的访问 3. 结构体传参 1. 结构体的声明 1.1 结构体的基础知识 结构是一些值的集合&…