二叉搜索树基本概念与实现

news2024/11/24 4:04:46

目录

基本概念

模拟实现

完整代码


基本概念

根的左节点比根小

根的右节点比根大

左右子树都满足

搜索二叉树的中序遍历是升序

模拟实现

完整代码

#pragma once

template<class K>
struct BSNode
{
	BSNode<K>* _left;
	BSNode<K>* _right;
	K _val;

	BSNode(const K& val)
		:_left(nullptr)
		, _right(nullptr)
		, _val(val)
	{

	}
};

template<class K>
class BSTree
{
	typedef BSNode<K> Node;
public:
	bool insert(const K& key)
	{
		if (_root == nullptr)
		{
			_root = new Node(key);
			return true;
		}
		Node* parent = nullptr;
		Node* cur = _root;
		while (cur)
		{
			if (cur->_val > key)
			{
				parent = cur;
				cur = cur->_left;
			}
			else if (cur->_val < key)
			{
				parent = cur;
				cur = cur->_right;
			}
			else
			{
				return false;
			}
		}
		cur = new Node(key);
		if (parent->_val > key)
		{
			parent->_left = cur;
		}
		else
		{
			parent->_right = cur;
		}
		return true;
	}

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

	bool Erase(const K& key)
	{
		Node* parent = nullptr;
		Node* cur = _root;
		while (cur)
		{
			if (cur->_val > key)
			{
				parent = cur;
				cur = cur->_left;
			}
			else if (cur->_val < key)
			{
				parent = cur;
				cur = cur->_right;
			}
			else
			{
				//左为空
				if (cur->_left == nullptr)
				{
					if (cur == _root)
					{
						_root = cur->_right;
					}
					else
					{
						if (cur == parent->_left)
						{
							parent->_left = cur->_right;
						}
						else
						{
							parent->_right = cur->_right;
						}
					}
					delete cur;
				}
				//右为空
				else if (cur->_right == nullptr)
				{
					if (cur == _root)
					{
						_root = cur->_left;
					}
					else
					{
						if (cur == parent->_left)
						{
							parent->_left = cur->_left;
						}
						else
						{
							parent->_right = cur->_left;
						}
					}
					delete cur;
				}
				//左右都不为空
				else
				{
					Node* parent = cur;
					Node* subnode = cur->_right;

					while (subnode->_left!=nullptr)
					{
						parent = subnode;
						subnode = subnode->_left;
					}
					swap(subnode->_val, cur->_val);
					
					if (subnode == parent->_left)
					{
						parent->_left = subnode->_right;
					}
					else
					{
						parent->_right = subnode->_right;
					}

					delete subnode;
				}
				return true;
			}
		}
		return false;
	}

	bool insertR(const K& key)
	{
		return _insertR(_root,key);
	}

	bool FindR(const K& key)
	{
		return _FindR(_root, key);
	}

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

	void Inorder()
	{
		_Inorder(_root);
		cout << endl;
	}

private:
	bool _insertR(Node*& root,const K& key)
	{
		if (root == nullptr)
		{
			root = new Node(key);
			return true;
		}

		if (root->_val < key)
		{
			_insertR(root->_right, key);
		}
		else if (root->_val > key)
		{
			_insertR(root->_left, key);
		}
		else
		{
			return false;
		}
	}

	bool _FindR(Node* root, const K& key)
	{
		if (root == nullptr)
		{
			return false;
		}

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

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

		if (root->_val > key)
		{
			return _EraseR(root->_left, key);
		}
		else if (root->_val < key)
		{
			return _EraseR(root->_right, key);
		}
		else
		{//删除
			if (root->_left == nullptr)
			{
				Node* del = root;
				root = root->_right;
				delete del;

				return true;
			}
			else if (root->_right == nullptr)
			{
				Node* del = root;
				root = root->_left;
				delete del;

				return true;
			}
			else
			{
				Node* subnode = root->_right;
				while (subnode->_left != nullptr)
				{
					subnode = subnode->_left;
				}
				swap(root->_val, subnode->_val);

				return _EraseR(root->_right, key);
			}
		}
	}

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

		_Inorder(root->_left);
		cout << root->_val << ' ';
		_Inorder(root->_right);
	}

	Node* _root = nullptr;
};

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

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

相关文章

【C语言程序设计】循环结构程序设计

目录 前言 一、程序设计第一题 二、程序设计第二题 三、程序设计第三题 总结 &#x1f308;嗨&#xff01;我是Filotimo__&#x1f308;。很高兴与大家相识&#xff0c;希望我的博客能对你有所帮助。 &#x1f4a1;本文由Filotimo__✍️原创&#xff0c;首发于CSDN&#x1f4da…

1.函数递归起(复习)

1.debug版本可以调试,realse版本不能调试 2.在realse版本中,代码已经得到了优化(编译器可能会自作主张地对代码进行优化),在大小和速度上都是最优的 3.ctrl F5 是开始执行不调试 4.设置好断点后,用F5到达该断点,相当于是到达了该断点的那个位置程序就先停止运行了 5.设立断…

Linux shell编程学习笔记35:seq

0 前言 在使用 for 循环语句时&#xff0c;我们经常使用到序列。比如&#xff1a; for i in 1 2 3 4 5 6 7 8 9 10; do echo "$i * 2 $(expr $i \* 2)"; done 其中的 1 2 3 4 5 6 7 8 9 10;就是一个整数序列 。 为了方便我们使用数字序列&#xff0c;Linux提供了…

UDS DTC状态掩码/DTC状态位

文章目录 简介用途依赖知识1、测试&#xff08;test&#xff09;2、操作循环&#xff08;operation cycle&#xff09;3、老化&#xff08;aging&#xff09; DTC状态位1、Bit 0&#xff1a;Test Failed2、Bit 1&#xff1a;Test Failed This operation cycle3、Bit 2&#xff…

【大数据】Hadoop生态未来发展的一些看法

大数据的起源 谷歌在2003到2006年间发表了三篇论文&#xff0c;《MapReduce: Simplified Data Processing on Large Clusters》&#xff0c;《Bigtable: A Distributed Storage System for Structured Data》和《The Google File System》介绍了Google如何对大规模数据进行存储…

基于51单片机的语音识别控制系统

0-演示视频 1-功能说明 &#xff08;1&#xff09;使用DHT11检测温湿度&#xff0c;然后用LCD12864显示&#xff0c;语音播放&#xff0c;使用STC11l08xe控制LD3320做语音识别&#xff0c; &#xff08;2&#xff09;上电时语音提示&#xff1a;欢迎使用声音识别系统&#xf…

数据结构篇-顺序表及单项链表

目录 一、学习目标 二、顺序表 1. 线性表 1.1 概念 1.2 举例 2. 顺序表 2.1 基本概念 2.2 基本操作 2.3 顺序表优缺点总结 三、单项链表 1. 基本概念 2. 链表的分类 无头节点&#xff1a; 有头节点&#xff1a; 增添加节点 查找节点 删除节点 链表遍历 销毁链…

【ARM Trace32(劳特巴赫) 使用介绍 13 -- Trace32 断点 Break 命令篇】

文章目录 1. Break.Set1.1 TRACE32 Break1.1.1 Break命令控制CPU的暂停1.2 Break.Set 设置断点1.2.1 Trace32 程序断点1.2.2 读写断点1.2.2.1 变量被改写为特定值触发halt1.2.2.2 设定非值触发halt1.2.2.4 变量被特定函数改写触发halt1.2.3 使用C/C++语法设置断点条件1.2.4 使用…

折点计数 C语言xdoj46

问题描述 给定n个整数表示一个商店连续n天的销售量。如果某天之前销售量在增长&#xff0c;而后一天销售量减少&#xff0c;则称这一天为折点&#xff0c;反过来如果之前销售量减少而后一天销售量增长&#xff0c;也称这一天为折点&#xff0c;其他的天都不是折点。如图…

AI大模型行业2024年上半年投资策略:大模型多模态化趋势显著,AI应用侧加速繁华

今天分享的AI系列深度研究报告&#xff1a;《AI大模型行业2024年上半年投资策略&#xff1a;大模型多模态化趋势显著&#xff0c;AI应用侧加速繁华》。 &#xff08;报告出品方&#xff1a;东莞证券&#xff09; 报告共计&#xff1a;30页 1.传媒行业行情和业绩回顾 1.1行业…

数据可视化:解析跨行业普及之道

数据可视化作为一种强大的工具&#xff0c;在众多行业中得到了广泛的应用&#xff0c;其价值和优势不断被发掘和利用。今天就让我以这些年来可视化设计的经验&#xff0c;讨论一下数据可视化在各个行业中备受青睐的原因吧。 无论是商业、科学、医疗保健、金融还是教育领域&…

spring 笔记一 spring快速入门和配置文件详解

Spring简介 Spring是分层的 Java SE/EE应用full-stack 轻量级开源框架&#xff0c;以 IoC&#xff08;Inverse Of Control&#xff1a;反转控制&#xff09;和AOP&#xff08;Aspect Oriented Programming&#xff1a;面向切面编程&#xff09;为内核。 提供了展现层SpringMV…

如何FL Studio显示中文?切换语言教程

你是不是也在为fl studio的英文界面而苦恼&#xff1f;你是不是也想让你的fl studio 说中文&#xff0c;方便你制作音乐&#xff1f;你是不是也在网上找了很多教程&#xff0c;却发现都是复杂的&#xff0c;或者已经过时的&#xff1f;如果你的答案是肯定的&#xff0c;那么你来…

c++国际象棋有人机qt5.9.9启动chesss

项目简介&#xff1a; 利用C的知识和QT以及一些自行拓展的新知识&#xff0c;实现国际象棋的开发。 使自己更加深层的理解和掌握c并在程序中展现出来&#xff0c;同时开发编程的思想和能力&#xff0c;以及扩展知识面&#xff0c;学习一些课上没有涉及的内容。同时通过阅读一…

应用程序映射的 5 个安全优势

现代企业依靠无数的软件应用程序来执行日常运营。这些应用程序相互连接并协同工作以提供所需的服务。了解这些应用程序如何相互交互以及底层基础设施对于任何组织都至关重要。这就是应用程序映射概念的用武之地。 顾名思义&#xff0c;应用程序映射是创建应用程序架构&#xf…

Java键值对Pair的使用方式和操作流程

Java键值对Pair的使用方式和操作流程 什么是键值对 键值对是一种常见的数据结构&#xff0c;它由一个唯一的键&#xff08;key&#xff09;和与之关联的值&#xff08;value&#xff09;组成。键和值之间存在一种映射关系&#xff0c;通过键可以查找或访问对应的值。 在键值对…

设计模式——原型模式(创建型)

引言 原型模式是一种创建型设计模式&#xff0c; 使你能够复制已有对象&#xff0c; 而又无需使代码依赖它们所属的类。 问题 如果你有一个对象&#xff0c; 并希望生成与其完全相同的一个复制品&#xff0c; 你该如何实现呢&#xff1f; 首先&#xff0c; 你必须新建一个属于…

【vue实战项目】通用管理系统:信息列表,信息的编辑和删除

本文为博主的vue实战小项目系列中的第七篇&#xff0c;很适合后端或者才入门的小伙伴看&#xff0c;一个前端项目从0到1的保姆级教学。前面的内容&#xff1a; 【vue实战项目】通用管理系统&#xff1a;登录页-CSDN博客 【vue实战项目】通用管理系统&#xff1a;封装token操作…

【日积月累】Spring中的AOP与IOC相关问题详解

Spring中的AOP与IOC 1.前言2.Spring AOP&#xff08;面向切面编程&#xff09;2.1 AOP的实现过程2.2 AOP代理模式的类型2.2.1JDK的动态代理2.2.2CGLIB的动态代理 2.3AOP应用常见场景2.3.1日志记录 2.4对AOP的理解 3.Spring IOC&#xff08;Inversion of Control&#xff0c;控…

【JVM从入门到实战】(五)类加载器

一、什么是类加载器 类加载器&#xff08;ClassLoader&#xff09;是Java虚拟机提供给应用程序去实现获取类和接口字节码数据的技术。 类加载器只参与加载过程中的字节码获取并加载到内存这一部分。 二、jdk8及之前的版本 类加载器分为三类&#xff1a; 启动类加载器-加载Ja…