【C++第十三课-二叉树进阶】二叉搜索树

news2024/9/22 13:24:14

目录

  • 二叉搜索树
    • 概念
    • 增,删,查
      • 1、删
      • 2、查
      • 3、增
    • 拷贝构造
    • 析构函数
    • 赋值
    • 增,删,查(递归)
      • 1、增(递归)
      • 2、删
      • 3、查
    • k搜索模型
    • kv搜索模型

二叉搜索树

概念

二叉搜索树又称二叉排序树,它或者是一棵空树。

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

增,删,查

1、删

bool Erase(const K& data)
	{
		Node* parent = nullptr;
		Node* cur = _root;
		if (_root == nullptr)
			return false;
		//找要删除的对象
		while (cur->_key != data && cur != nullptr)
		{
			if (cur->_key > data)
			{
				parent = cur;
				cur = cur->_left;
			}
			else if (cur->_key < data)
			{
				parent = cur;
				cur = cur->_right;
			}
		}
		//没找到要删除的对象
		if (cur == nullptr)
			return false;
		//找到了要删除的对象
		//1、删除的是叶子
		if (cur->_left == nullptr && cur->_right == nullptr)
		{
			if (parent->_left == cur)
				parent->_left = nullptr;
			if (parent->_right == cur)
				parent->_right = nullptr;
		}
		//2、只有左孩子或右孩子
		if (cur->_left != nullptr && cur->_right == nullptr)
		{
			if (parent->_left == cur)
				parent->_left = cur->_left;
			if (parent->_right == cur)
				parent->_right = cur->_left;
		}
		if (cur->_right != nullptr && cur->_left == nullptr)
		{
			if (parent->_left == cur)
				parent->_left = cur->_right;
			if (parent->_right == cur)
				parent->_right = cur->_right;
		}
		//3、左右孩子都有,左孩子放到右孩子的最左边
		if (cur->_right != nullptr && cur->_left != nullptr)
		{
			Node* l = cur->_left;
			Node* r = cur->_right;
			Node* p = r;
			while (p->_left != nullptr)
			{
				p = p->_left;
			}
			p->_left = l;
			if (parent->_left == cur)
				parent->_left = r;
			if (parent->_right == cur)
				parent->_right = r;
		}

		delete cur;
		cur = nullptr;
		return true;
	}

问题:
上面这个方法不好,例如当树很深的时候
替换删除法:找一个能替换我的节点,交换值,转换删除他
一个孩子和没有孩子可以看出一类

修改

bool Erase(const K& data)
	{
		//先找到data的节点
		Node* cur = _root;
		Node* parent = _root;
		while (cur)
		{
			if (cur->_key > data)
			{
				parent = cur;
				cur = cur->_left;
			}
			else if (cur->_key < data)
			{
				parent = cur;
				cur = cur->_right;
			}
			//找到了
			else
			{
				//1、只有一个孩子或没有孩子
				if (cur->_left == nullptr)
				{
					if (parent->_left == cur)
						parent->_left = cur->_right;
					if (parent->_right == cur)
						parent->_right = cur->_right;
					delete cur;
					cur = nullptr;
					return true;
				}
				if (cur->_right == nullptr)
				{
					if (parent->_left == cur)
						parent->_left = cur->_left;
					if (parent->_right == cur)
						parent->_right = cur->_left;
					delete cur;
					cur = nullptr;
					return true;
				}
				//1、有两个孩子
				Node* rcur = cur->_right;
				Node* rparent = cur;
				while (rcur->_left)
				{
					rparent = rcur;
					rcur = rcur->_left;
				}
				cur->_key = rcur->_key;
				if (rparent->_left == rcur)
					rparent->_left = rcur->_right;
				if (rparent->_right == rcur)
					rparent->_right = rcur->_right;
				delete rcur;
				rcur = nullptr;
				return true;
			}
		}
	}

2、查

3、增

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

拷贝构造

	BSTree<int> t;
	t.InsertR(8);
	t.InsertR(3);
	t.InsertR(6);
	t.InsertR(7);
	t.InsertR(4);
	t.InsertR(1);
	t.InsertR(10);
	t.InsertR(14);
	t.InsertR(13);
	t.InOrder();
	BSTree<int> t2(t);

在这里插入图片描述
上面这个拷贝构造是我自己写的,虽然根据树1深拷贝了树2,但是没法给树2的_root。也就是Copy函数缺少一个返回值
补充

	//强制生成默认构造
	BSTree() = default;
	//强制生成默认构造
	BSTree() = default;

	Node*& Copy(Node*& root1)
	{
		if (root1 == nullptr)
			return nullptr;
		Node*& Newnode = new Node(root1->_key);
		Newnode->_left = Copy(root1->_left);
		Newnode->_right = Copy(root1->_right);
		return Newnode;
	}
	BSTree(const BSTree<K>& t)
	{
		_root = Copy(t->_root);
	

析构函数

	~BSTree()
	{
		Destroy(_root);
	}
	void Destory(Node*& root)
	{
		if (root == nullptr)
			return;
		Destory(root->_left);
		Destory(root->_right);
		delete root;
	}

赋值

	BSTree<K>& operator=(BSTree<K> t)
	{
		swap(_root, t._root);
		return *this;
	}

增,删,查(递归)

引用不能改变指向

1、增(递归)

关键点:如何和父亲链接

bool _InsertR(Node*& root, const K& key)
	{
		if (root == nullptr)
		{
			root = new Node(key);
			return true;
		}
		if (root->_key < key)
		{
			if (root->_right == nullptr)
			{
				root->_right = new Node(key);
				return true;
			}
			else
			{
				return _InsertR(root->_right, key);
			}
		}
		else if (root->_key > key)
		{
			if (root->_left == nullptr)
			{
				root->_left = new Node(key);
				return true;
			}
			else
			{
				return _InsertR(root->_left, key);
			}
		}
		else
			return false;
	}

上面还是有冗余

	bool InsertR(const K& key)
	{
		return _InsertR(_root, key);
	}
	bool _InsertR(Node*& root, const K& key)
	{
		if (root == nullptr)
		{
			root = new Node(key);
			return true;
		}
		if (root->_key < key)
		{
			return _InsertR(root->_right, key);
		}
		else if (root->_key > key)
		{
			return _InsertR(root->_left, key);
		}
		else
			return false;
	}

引用是关键

2、删

	bool EraseR(const K& key)
	{
		return _EraseR(_root, key);
	}

	bool _EraseR(Node*& root, const K& key)
	{
		if (root == nullptr)
			return false;
		if (root->_key < key)
		{
			return _EraseR(root->_right, key);
		}
		else if (root->_key > key)
		{
			return _EraseR(root->_left, key);
		}
		else
		{
			Node* del = root;
			if (root->_left == nullptr)
				root = root->_right;
			else if (root->_right == nullptr)
				root = root->_left;
			else
			{
				Node* RightMin = root->_right;
				while (RightMin->_left)
				{
					RightMin = RightMin->_left;
				}
				swap(root->_key, RightMin->_key);
				return _EraseR(root->_right, key);
			}
			delete del;
			return true;
		}
	}

3、查

	bool FindR(const K*& key)
	{
		return _FindR(_root, key);
	}
	bool _FindR(Node* _root, K key)
	{
		if (_root == nullptr)
			return false;
		if (_root->_key < key)
			return _FindR(_root->_right, key);
		else if (_root->_key > key)
			return _FindR(_root->_left, key);
		else
			return true;
	}

k搜索模型

快速查找一个值是否存在?
例子
小区内部车库:进出都有快速查看你的车牌号是否是小区住户
门禁

kv搜索模型

快速通过一个值(key)查找另一个值(value)是否存在?
例子
商场的车库:进去是都可以进,出去的时候需要通过车牌号快速查找你停入的时间,判断是否超过半个小时。若没有超过半小时直接抬杆,若超过半个小时计算应付费用再抬杆
字典查询
高铁用身份证进站

namespace key_value
{
	template<class K, class V>
	class BSTreeNode
	{
		typedef BSTreeNode<K, V> Node;
	public:
		BSTreeNode(const K& key = 0, const V& value = 0)
			:_key(key)
			,_value(value)
			, _left(nullptr)
			, _right(nullptr)
		{}
		Node* _left;
		Node* _right;
		K _key;
		V _value;

	};

	template<class K, class V>
	class BSTree
	{
		typedef BSTreeNode<K, V> Node;
	public:
		void InOrder()
		{
			_InOrder(_root);
		}
		bool Erase(const K& data)
		{
			//先找到data的节点
			Node* cur = _root;
			Node* parent = _root;
			while (cur)
			{
				if (cur->_key > data)
				{
					parent = cur;
					cur = cur->_left;
				}
				else if (cur->_key < data)
				{
					parent = cur;
					cur = cur->_right;
				}
				//找到了
				else
				{
					//1、只有一个孩子或没有孩子
					if (cur->_left == nullptr)
					{
						if (parent->_left == cur)
							parent->_left = cur->_right;
						if (parent->_right == cur)
							parent->_right = cur->_right;
						delete cur;
						cur = nullptr;
						return true;
					}
					if (cur->_right == nullptr)
					{
						if (parent->_left == cur)
							parent->_left = cur->_left;
						if (parent->_right == cur)
							parent->_right = cur->_left;
						delete cur;
						cur = nullptr;
						return true;
					}
					//1、有两个孩子
					Node* rcur = cur->_right;
					Node* rparent = cur;
					while (rcur->_left)
					{
						rparent = rcur;
						rcur = rcur->_left;
					}
					swap(cur->_key, rcur->_key);
					swap(cur->_value, rcur->_value);
					if (rparent->_left == rcur)
						rparent->_left = rcur->_right;
					if (rparent->_right == rcur)
						rparent->_right = rcur->_right;
					delete rcur;
					rcur = nullptr;
					return true;
				}
			}
		}
		Node* FindR(const K& key)
		{
			return _FindR(_root, key);
		}
		bool InsertR(const K& key, const V& value)
		{
			return _InsertR(_root, key, value);
		}
		bool EraseR(const K& key)
		{
			return _EraseR(_root, key);
		}

	private:
		Node* _FindR(Node* _root, K key)
		{
			if (_root == nullptr)
				return nullptr;
			if (_root->_key < key)
				return _FindR(_root->_right, key);
			else if (_root->_key > key)
				return _FindR(_root->_left, key);
			else
				return _root;
		}
		void _InOrder(Node* _root)
		{
			if (_root == nullptr)
				return;
			_InOrder(_root->_left);
			cout << _root->_key << " ";
			_InOrder(_root->_right);
		}
		Node*& Copy(Node*& root1)
		{
			if (root1 == nullptr)
				return nullptr;
			Node*& Newnode = new Node(root1->_key);
			Newnode->_left = Copy(root1->_left);
			Newnode->_right = Copy(root1->_right);
			return Newnode;
		}
		bool _InsertR(Node*& root, const K& key, const V& value)
		{
			if (root == nullptr)
			{
				root = new Node(key, value);
				return true;
			}
			if (root->_key < key)
			{
				return _InsertR(root->_right, key, value);
			}
			else if (root->_key > key)
			{
				return _InsertR(root->_left, key, value);
			}
			else
				return false;
		}
		bool _EraseR(Node*& root, const K& key)
		{
			if (root == nullptr)
				return false;
			if (root->_key < key)
			{
				return _EraseR(root->_right, key);
			}
			else if (root->_key > key)
			{
				return _EraseR(root->_left, key);
			}
			else
			{
				Node* del = root;
				if (root->_left == nullptr)
					root = root->_right;
				else if (root->_right == nullptr)
					root = root->_left;
				else
				{
					Node* RightMin = root->_right;
					while (RightMin->_left)
					{
						RightMin = RightMin->_left;
					}
					swap(root->_key, RightMin->_key);
					swap(root->_value, RightMin->_value);
					return _EraseR(root->_right, key);
				}
				delete del;
				return true;
			}
		}
		Node* _root = nullptr;
	};
}

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

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

相关文章

创建微服务组件

1.1 数据库表 shop_order订单表 shop_product商品表 shop_user⽤户表 1.2 服务模块 1.2.1 创建模块 创建公共⽗模块springcloud_alibaba 创建公共模块 shop_common ,⽤于存放公共的实体类和⼯具类 创建订单微服务模块 shop_order 端⼝809X 创建商品微服务模块 shop_product …

同鑫eHR人力资源管理系统 GetFlowDropDownListItems SQL注入漏洞复现

0x01 产品简介 同鑫eHR,聚焦人力资源管理痛点,首创提出人力资源管理系统一体化概念,打造应用一体化、数据一体化、流程一体化、终端一体化的人力资源管理系统一体化解决方案。为广大企业解决系统功能分散不同步、业务数据零散无价值、流程可自定义程度低、行业深度问题无法…

【ceph学习】ceph如何进行数据的读写(1)

版本 ceph版本为17. ceph如何进行读写接口的实现 Ceph的客户端通过librados的接口进行集群的访问&#xff0c;这里的访问包括&#xff1a; 1&#xff09;对集群的整体访问 2&#xff09;对象的访问 两类接口&#xff0c;这套接口&#xff08;API&#xff09;包括C、C和Pytho…

在读本科生可以考PMP吗?

PMP认证与学历无关&#xff0c;但在报考条件上需要留意以下几点&#xff1a; 学历要求&#xff1a;年满23周岁/高中毕业5年以上/ 大专毕业3年以上&#xff0c;只需满足其中一个条件即可&#xff1b; 证明要求&#xff1a;必须具备35学时&#xff08;PDU&#xff09;证明&…

值得收藏 猫咪浮毛异味难清理?三种有效的除毛工具来帮你

养猫一时爽&#xff0c;除毛火葬场&#xff01;我接老大布偶回家以来&#xff0c;都没怎么掉毛&#xff0c;还挺开心的。然后觉得可以负担得起第二只小猫&#xff0c;就养多一只老二银渐层。结果没接回来多久&#xff0c;我的”报应“来了...遇上换毛季&#xff0c;两只猫像是觉…

操作系统识别——CSP-J1真题讲解

【题目】 以下哪个不是操作系统?( ) A. Linux B. Windows C. Android D. HTML 【答案】 D 【解析】 操作系统&#xff08;Operating System&#xff0c;缩写&#xff1a;OS&#xff09;相当于电脑的管家&#xff0c;管理着计算机的硬件与软件资源&#xff0c;以供电…

分享一个基于springboot的中小学数字化教学资源管理平台java互动式教学资源学习与交流平台(源码、调试、LW、开题、PPT)

&#x1f495;&#x1f495;作者&#xff1a;计算机源码社 &#x1f495;&#x1f495;个人简介&#xff1a;本人 八年开发经验&#xff0c;擅长Java、Python、PHP、.NET、Node.js、Android、微信小程序、爬虫、大数据、机器学习等&#xff0c;大家有这一块的问题可以一起交流&…

俄罗斯市场应用程序翻译的特点

向俄罗斯市场扩张为应用程序开发人员带来了一系列独特的挑战和机遇。俄罗斯人口众多&#xff0c;精通技术&#xff0c;具有巨大地增长潜力。然而&#xff0c;为了在这个市场上取得成功&#xff0c;开发人员必须确保他们的应用程序得到有效地翻译和本地化&#xff0c;以满足俄罗…

【IoT】将各类遥控器(红外,频射,蓝牙,wifi,Zigbee)等设备接入米家,实现家庭物联网设备控制(以极米Z7X投影仪为例)

【IoT】将各类遥控器&#xff08;红外&#xff0c;频射&#xff0c;蓝牙&#xff0c;wifi&#xff0c;加密&#xff09;等设备接入米家&#xff0c;实现家庭物联网设备控制&#xff08;以极米Z7X投影仪为例&#xff09; 文章目录 1、三种主流遥控方式&#xff08;红外&#xff…

差旅费用报销之合规性管理

除了在差旅报销流程简化和效率提升方面表现抢眼&#xff0c;差旅费用报销平台分贝通在报销方案的合规性管理方面也有自己的“专长”&#xff0c;以确保合作企业的费用报销流程符合预算规则和法规政策&#xff0c;降低差旅管理成本和风险。 费用报销合规性之政策合规 首先&…

信息安全数学基础(1)整除的概念

前言 在信息安全数学基础中&#xff0c;整除是一个基础且重要的概念。它涉及整数之间的特定关系&#xff0c;对于理解数论、密码学等领域至关重要。以下是对整除概念的详细阐述&#xff1a; 一、定义 设a, b是任意两个整数&#xff0c;其中b ≠ 0。如果存在一个整数q&#xff0…

C++ | Leetcode C++题解之第375题猜数字大小II

题目&#xff1a; 题解&#xff1a; class Solution { public:int getMoneyAmount(int n) {vector<vector<int>> f(n1,vector<int>(n1));for (int i n - 1; i > 1; i--) {for (int j i 1; j < n; j) {f[i][j] j f[i][j - 1];for (int k i; k &l…

深度学习速通系列:标准化和归一化

在数据处理中&#xff0c;“标准化”&#xff08;Standardization&#xff09;和"归一化"&#xff08;Normalization&#xff09;是两种常用的数据预处理技术&#xff0c;它们用于调整数据的尺度&#xff0c;使得数据在分析或模型训练中更加公平和有效。 下面是两种…

《系统架构设计师教程(第2版)》第17章-通信系统架构设计理论与实践-01-局域网网络架构

文章目录 1. 局域网络架构概述2. 网络组成3 网络架构3.1 单核心架构3.2 双核心架构3.3 环型架构3.4 层次局域网架构 4. 网络协议的应用 通信系统网络架构 包括&#xff1a;局域网、广域网、移动通信网等 1. 局域网络架构概述 特点&#xff1a; 覆盖地理范围小数据传输速率高…

自定义校验--校验json长度

mysql8中支持json格式的字段&#xff0c;某些情况下使用很方便&#xff0c;但也带来一个问题&#xff0c;就是它的最大长度不能设置&#xff0c;最大支持4GB&#xff0c;如果有恶意程序保存一条4GB的数据进去&#xff0c;估计这张表就要卡死了,所以要加一个自定义校验&#xff…

人体行走步态周期转换为不同相位描述

目录 一、步行周期 二、相关论文描述 三、参考文献 一、步行周期 人体行走时的步态状态通常采用传感器进行判断&#xff0c;比如Dong Jin Hyun等[1]通过嵌入两个力感应电阻的鞋垫来估计的步行状态&#xff0c;其中一个检测脚趾接触&#xff0c;另一个检测脚后跟接触[5]。Con…

制造企业SRM系统中如何进行供应商的管理

一、供应商选择与评估 在SRM系统中&#xff0c;供应商的选择和评估是第一步。企业需要建立一套科学的评估体系&#xff0c;涵盖以下几个关键方面&#xff1a; 1. 质量&#xff1a;评估供应商的产品质量、质量控制体系和质量改进能力。 2. 成本&#xff1a;分析供应商的价格竞…

华为2024 届秋招招聘——硬件技术工程师-电源方向-机试题(四套)(每套四十题)

华为 2024 届秋招——硬件-电源机试题&#xff08;四套&#xff09;&#xff08;每套四十题&#xff09; 岗位——硬件技术工程师 岗位意向——电源 真题题目分享&#xff0c;完整版带答案(有答案和解析&#xff0c;答案非官方&#xff0c;未仔细校正&#xff0c;仅供参考&am…

【python】一招教会你,python爬虫过程中怎么快速随机生成userAgent

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全…

rkllm模型量化构建

在发布的 RKLLM 工具链压缩文件中&#xff0c;包含了 RKLLM-Toolkit 的 whl 安装包、RKLLM Runtime 库的相关文件以及参考示例代码&#xff0c;github链接如下&#xff1a;https://github.com/airockchip/rknn-llm 环境准备 RKLLM-Toolkit 由于提供的rkllm_toolkit包为pytho…