C++实现二叉搜索树的增删查改(非递归玩法)

news2024/11/16 19:37:55

文章目录

    • 一、二叉搜索树的概念结构和时间复杂度
    • 二、二叉搜索树的插入
    • 三、二叉搜索树的查找
    • 四、二叉搜索树的删除(最麻烦,情况最多,一一分析)
      • 3.1首先我们按照一般情况下写,不考虑特殊情况下
        • 4.1.1左为空的情况(与右为空的情况差不多)
        • 4.1.2两边都不为空的情况下
      • 4.1其次我们考虑极端情况,如果刚好是整体树的根要删除
    • 五、二叉搜索树的中序遍历
    • 六、二叉搜索树的拷贝构造函数,析构函数,赋值操作
      • 6.1 赋值操作(比较简单)
      • 6.2拷贝构造
      • 6.3析构函数
    • 七、全部源码展现(递归玩法的代码也传进来了,下次讲解)

在这里插入图片描述


先赞后看,养成习惯!!!^ _ ^<3 ❤️ ❤️ ❤️
码字不易,大家的支持就是我坚持下去的动力。点赞后不要忘了关注我哦!
所属专栏:C++进阶
在这里插入图片描述

一、二叉搜索树的概念结构和时间复杂度

二叉搜索树(Binary Search Tree)又称二叉排序树(Binary Sort Tree),是一种特殊类型的二叉树,它所有的根节点大于左子树的节点,小于右子树的节点,对二叉搜索树进行中序遍历,即可得到有序的数列。二叉搜索树的时间复杂度由树的高度决定,其搜索、插入和删除的时间复杂度均为 O(log n),其中 n 是节点数。在最坏的情况下,仍然会有 O(n)的时间复杂度。
在这里插入图片描述

二、二叉搜索树的插入

首先定义一个命名空间作用域,在域中进行插入操作,构造一个二叉树的节点,对节点进行初始化构造

namespace key
{
	template<class K>
	struct BSTreeNode
	{

		typedef BSTreeNode<K> Node;
		BSTreeNode(const K& key)
			:left(nullptr), 
			right(nullptr),
			_key(key)
		{}
		Node* left;
		Node* right;
		K _key;
	};
	template<class K>
	class BSTree
	{
	public:
	bool Insert(const K& key)
	{
	Node* root = new Node(key);
	if (_root == nullptr)
	{
		_root = root;
		return true;
	}
	Node* parent = nullptr;
	Node* cur = _root;
	while (cur)
	{
		if (cur->_key > root->_key)
		{
			parent = cur;
			cur = cur->left;
		}
		else if (cur->_key < root->_key)
		{
			parent = cur;
			cur = cur->right;
		}
		else
		{
			return false;
		}
	}
	if (parent->_key < root->_key)
		parent->right = root;
	else
		parent->left = root;
	return true;
	}
}

代码图解:
在这里插入图片描述

三、二叉搜索树的查找

查找非常简单按照流程找就行了

typedef BSTreeNode<K> Node;
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
		{
			return true;
		}
	}
	return false;
}

四、二叉搜索树的删除(最麻烦,情况最多,一一分析)

3.1首先我们按照一般情况下写,不考虑特殊情况下

bool Erase(const K& key)
{
	assert(_root);
	Node* parent = nullptr;
	Node* cur = _root;

	while (cur)
	{
		if (cur->_key > key)
		{
			parent = cur;
			cur = cur->left;
		}
		else if (cur->_key < key)
		{
			parent = cur;
			cur = cur->right;
		}
		else
		{
			if (cur->left == nullptr)
			{
					if (parent->left == cur)
					{
						parent->left = cur->right;

					}
					else
					{
						parent->right = cur->right;

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

					}
					else
					{
						parent->right = cur->left;

					}
				delete cur;
				return true;
			}
			else
			{
				Node* pminleft = cur;
				Node* minleft = cur->right;
				while (minleft->left)
				{
					pminleft = minleft;
					minleft = minleft->left;
				}
				cur->_key = minleft -> _key;
				if (minleft == pminleft->left)
					pminleft->left = minleft->right;
				else
					pminleft->right = minleft->right;
				delete minleft;
				return true;
			}
		}
		
	}
	
	return false;
}

代码图解(解释找到时候的情况)

4.1.1左为空的情况(与右为空的情况差不多)

在这里插入图片描述

4.1.2两边都不为空的情况下

在这里插入图片描述

4.1其次我们考虑极端情况,如果刚好是整体树的根要删除

在这里插入图片描述
调整代码如下

				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;
				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;
				return true;
}

五、二叉搜索树的中序遍历

这里我们用了一个小技巧,就是通过类里面的函数调用类里面的私有成员

//中序遍历
void _Inorder()
{
	Inorder(_root);
}
private:
	//中序遍历
	void Inorder(Node* root)
	{
		if (root == nullptr)
			return;
		Inorder(root->left);
		cout << root->_key << ' ';
		Inorder(root->right);
	}
	Node* _root = nullptr;

六、二叉搜索树的拷贝构造函数,析构函数,赋值操作

6.1 赋值操作(比较简单)

BSTree<K>& operator=(const BSTree& root)
{
	swap(_root, root->_root);
	return *this;
}

6.2拷贝构造

BSTree(const BSTree<K>& t)
{
	_root = Copy(t._root);
}
Node* Copy(Node* root)
{
	if (root == nullptr)
		return nullptr;
	Node* newroot = new Node(root->_key);
	newroot->left = Copy(root->left);
	newroot->right = Copy(root->right);
	return newroot;
}

6.3析构函数

~BSTree()
{
	Distroy(_root);
}
void Distroy(Node* root)
{
	if (root == nullptr)
		return;
	Distroy(root->left);
	Distroy(root->right);
	delete root;
}

七、全部源码展现(递归玩法的代码也传进来了,下次讲解)

#pragma once
#include<iostream>
#include<assert.h>
#include<algorithm>
using namespace std;

namespace key
{
	template<class K>
	struct BSTreeNode
	{

		typedef BSTreeNode<K> Node;
		BSTreeNode(const K& key)
			:left(nullptr), 
			right(nullptr),
			_key(key)
		{}
		Node* left;
		Node* right;
		K _key;
	};



	template<class K>
	class BSTree
	{
	public:
	//查
		BSTree() = default;//自动生成默认构造


		~BSTree()
		{
			Distroy(_root);
		}

		BSTree(const BSTree<K>& t)
		{
			_root = Copy(t._root);
		}

		BSTree<K>& operator=(const BSTree& root)
		{
			swap(_root, root->_root);
			return *this;
		}

		typedef BSTreeNode<K> Node;
		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
				{
					return true;
				}
			}
			return false;
		}

	//增
		bool Insert(const K& key)
		{
			Node* root = new Node(key);
			if (_root == nullptr)
			{
				_root = root;
				return true;
			}
			Node* parent = nullptr;
			Node* cur = _root;
			while (cur)
			{
				if (cur->_key > root->_key)
				{
					parent = cur;
					cur = cur->left;
				}
				else if (cur->_key < root->_key)
				{
					parent = cur;
					cur = cur->right;
				}
				else
				{
					return false;
				}
			}
			if (parent->_key < root->_key)
				parent->right = root;
			else
				parent->left = root;
			return true;

		}

		//删
		bool Erase(const K& key)
		{
			assert(_root);
			Node* parent = nullptr;
			Node* cur = _root;

			while (cur)
			{
				if (cur->_key > key)
				{
					parent = cur;
					cur = cur->left;
				}
				else if (cur->_key < 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;
						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;
						return true;
					}
					else
					{
						Node* pminleft = cur;
						Node* minleft = cur->right;
						while (minleft->left)
						{
							pminleft = minleft;
							minleft = minleft->left;
						}
						cur->_key = minleft -> _key;
						if (minleft == pminleft->left)
							pminleft->left = minleft->right;
						else
							pminleft->right = minleft->right;
						delete minleft;
						return true;
					}
				}
				
			}
			
			return false;
		}


		/		
		//递归玩法

		//增
		bool _InsertR(const K& key)
		{
			_Insert(_root,key);
		}

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

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

		

		void Distroy(Node* root)
		{
			if (root == nullptr)
				return;
			Distroy(root->left);
			Distroy(root->right);
			delete root;
		}
		
		//中序遍历
		void _Inorder()
		{
			Inorder(_root);
		}
		

		private:
			//中序遍历
			void Inorder(Node* root)
			{
				if (root == nullptr)
					return;
				Inorder(root->left);
				cout << root->_key << ' ';
				Inorder(root->right);
			}

			bool _Insert(Node*& root,const K& key)
			{
				if (root == nullptr)
				{
					Node* newroot = new Node(key);
					root = newroot;
					return true;
				}
				if (root->_key > key)
				{
					_Insert(root->left, key);
				}
				else if (root->_key < key)
				{
					_Insert(root->right, key);
				}
				else
					return false;
			}

			Node& _Find(Node*& root, const K& key)
			{
				if (root == nullptr)
					return nullptr;
				if (root->_key > key)
				{
					_Find(root->left);
				}
				else if (root->_key < key)
				{
					_Find(root->right);
				}
				else
				{
					return root;
				}
			}

			Node* Copy(Node* root)
			{
				if (root == nullptr)
					return nullptr;
				Node* newroot = new Node(root->_key);
				newroot->left = Copy(root->left);
				newroot->right = Copy(root->right);
				return newroot;
			}

			bool _Erase(Node*& root, const K& key)
			{
				if (root == nullptr)
					return false;
				if (root->_key > key)
				{
					return _Erase(root->left,key);
				}
				else if(root->_key < key)
				{
					return _Erase(root->right ,key);
				}
				else
				{
					Node* minright = root->right;
					while (minright->left)
					minright = minright->left;
					swap(root->_key,minright->_key);

					minright->right = minright->right;
					delete minright;

					return true;
				}
			}

			Node* _root = nullptr;
	};
}

在这里插入图片描述

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

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

相关文章

小波降噪基础-python版本

这篇小文将使用小波多分辨分析对一个简单信号进行降噪&#xff0c;主要是降噪流程&#xff0c;为以后的小波更复杂的降噪算法打下良好的基础。降噪算法流程大致如下&#xff1a; &#xff08;1&#xff09;去趋势项&#xff08;如直流电流&#xff09;&#xff0c;并将数据归一…

词向量模型评估

一、既有范式 词向量的语言学特性&#xff1a;这部分主要通过一些具体的指标来评估词向量是否能捕捉到语言的内在规律&#xff0c;包括&#xff1a; 相似度评价指标&#xff1a;检查词向量空间中距离近的词是否与人类直觉一致&#xff0c;例如&#xff0c;利用余弦相似度来评估…

【嵌入式智能产品开发实战】(十三)—— 政安晨:通过ARM-Linux掌握基本技能【运行环境】

目录 简述 开始 操作系统环境下的程序运行 裸机环境下的程序运行 程序入口main()函数分析 BSS段的小提示 政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: 嵌入式智能产品开发实战 希望政安晨的博客能够对您有所裨益&#xff0c;如有不…

基于Java的高校成绩报送系统的设计与实现

基于Java的高校成绩报送系统的设计与实现 获取源码——》哔站搜&#xff1a;计算机专业毕设大全 获取源码——》哔站搜&#xff1a;计算机专业毕设大全

计算机基础入门7:大学计算机基础

第1章 计算机的基本概念 1.1 计算机概述 1、 电子计算机{电子模拟计算机&#xff0c;电子数字计算机} 2、 计算机之父——冯诺依曼(J. Von Neumann)&#xff0c;奠定现代计算机的体系结构。 3、 冯诺依曼在EDVAC设计方案中提出了“存储程序”原理 4、 计算机的三个特征&…

【Spring】SpringBoot整合Redis,用Redis实现限流(附Redis解压包)

&#x1f4dd;个人主页&#xff1a;哈__ 期待您的关注 本文介绍SpringBoot整合Redis并且进行接口的限流&#xff0c;文章主要介绍的是一种思想&#xff0c;具体代码还要结合实际。 一、Windows安装Redis Redis的解压包我放在了百度网盘上&#xff0c;有需要的可以下载。 R…

java自动化测试-03-05java基础之字符串

1、字符串的定义 String是变量类型&#xff0c;表示字符串类型 name是给这个变量起的名字&#xff0c;这个是可以随意取的&#xff0c;只要不是java的关键字就可以了 表示赋值&#xff0c;右边的的内容表示 变量值&#xff0c;对字符串变量进行 赋值&#xff0c;需要用双引号…

C++模板实参推断

模板实参推断 我们已经看到&#xff0c;对于函数模板&#xff0c;编译器利用调用中的函数实参来确定其模板参数。 从函数实参来确定模板实参的过程被称为模板实参推断。 也就是说&#xff0c;只有函数参数才配有模板实参推断&#xff0c;函数返回类型是不配有的 在模板实参…

每日面经分享(python part1)

Python中的深拷贝和浅拷贝的区别是什么&#xff1f; a. 浅拷贝创建一个新的对象&#xff0c;但其中的可变元素仍然共享引用。只有对象的第一层被复制&#xff0c;而更深层次的嵌套对象仍然是引用。更改其中一个对象的属性会影响到其他对象。 b. 深拷贝创建一个完全独立的新对象…

营销中的归因人工智能

Attribution AI in marketing 归因人工智能作为智能服务的一部分&#xff0c;是一种多渠道算法归因服务&#xff0c;根据特定结果计算客户互动的影响和增量影响。有了归因人工智能&#xff0c;营销人员可以通过了解每个客户互动对客户旅程每个阶段的影响来衡量和优化营销和广告…

MT3017 上色

思路&#xff1a;使用分治&#xff0c;在每个连续区域递归调用heng()和shu() #include <bits/stdc.h> using namespace std; int n, m; int h[5005];int shu(int l, int r) {return r - l 1; } int heng(int l, int r) {int hmin 0x3f3f3f3f;for (int i l; i < r;…

银行数字化转型导师坚鹏:银行数字化转型给总行带来的9大价值

银行数字化转型给总行带来的9大价值 银行数字化转型对总行的深远影响是多方面的&#xff0c;银行数字化转型导师坚鹏从以下9个方面进行详细分析&#xff0c;相信能够给您带来重要价值。 1. 客户价值 银行数字化转型可以利用大数据、智能化风控模型为客户设计、提供“千人千面…

多模态系列-综述Video Understanding with Large Language Models: A Survey

本文是LLM系列文章,针对《Video Understanding with Large Language Models: A Survey》的翻译。 论文链接:https://arxiv.org/pdf/2312.17432v2.pdf 代码链接:https://github.com/yunlong10/Awesome-LLMs-for-Video-Understanding 大型语言模型下的视频理解研究综述 摘要…

Python学习笔记-Flask接收post请求数据并存储数据库

1.引包 from flask import Flask, request, jsonify from flask_sqlalchemy import SQLAlchemy 2.配置连接,替换为自己的MySQL 数据库的实际用户名、密码和数据库名 app Flask(__name__) #创建应用实列 app.config[SQLALCHEMY_DATABASE_URI] mysqlpymysql://ro…

Linux笔记之制作基于ubuntu20.4的最小OpenGL C++开发docker镜像

Linux笔记之制作基于ubuntu20.4的最小OpenGL C开发docker镜像 —— 2024-04-03 夜 code review! 文章目录 Linux笔记之制作基于ubuntu20.4的最小OpenGL C开发docker镜像1.这里把这本书的例程代码放在了Dockerfile所在的文件夹内以使镜像预装例程代码2.创建Dockerfile3.构建Do…

c++前言

目录 1. 什么是 C 2. C 发展史 3. C 的重要性 4. 如何学习 C 5. 关于本门课程 1. 什么是C C语言是结构化和模块化的语言&#xff0c;适合处理较小规模的程序。对于复杂的问题&#xff0c;规模较大的 程序&#xff0c;需要高度的抽象和建模时&#xff0c; C 语言则不合适…

ShardingJdbc+Mybatis实现多数据源

Mybatis多数据源 这个是对shardingjdbc应用的一个升级&#xff0c;如果对于shardingjdbc的整合还没看过之前的文章的&#xff0c;可以先看看文章https://blog.csdn.net/Think_and_work/article/details/137174049?spm1001.2014.3001.5501 整合步骤 1、依赖 和全新项目的单…

【异常错误】 Expected to have finished reduction in the prior iteration before star、find_unused_parameters

运行代码时出现了错误&#xff1a; RuntimeError: Expected to have finished reduction in the prior iteration before starting a new one. This error indicates that your module has parameters that were not used in producing loss. You can enable unused parameter …

VSCODE使用VSIX安装扩展

VSCode安装扩展特别慢&#xff0c;使用命令行安装告别龟速&#xff1a; code --install-extension当然&#xff0c;我这个是在WSL 的linux上安装的&#xff0c;Windows一样的。 VSCode扩展商店网页链接&#xff1a;https://marketplace.visualstudio.com/vscode

Ceph分布式存储系统以及高可用原理

Ceph分布式存储系统以及高可用原理 1. Ceph原理和架构1.1 分布式存储系统抽象1.2 Ceph基本组件 2 Ceph中的策略层2.1 CRUSH进行数据分发和定位2.2 PG(Placement Group): 集群管理的基本单元2.3 PG的代理primary OSD2.4 轻量级的集群元数据ClusterMap2.5 对PG的罗辑分组&#xf…