二叉搜索树的实现(C++)

前言

二叉搜索树(搜索二叉树,Binary search tree)是一种特殊的二叉树。其规则为:左子树的值一定小于等于根,右子树的值一定大于等于根,并且左右子树也为搜索二叉树。

二叉搜索树的插入

1.若树为空,插入的数据为根节点的数据

2.若树不为空,按照二叉搜索树的性质,判断节点的值与插入值的大小关系。若大于节点的值则往右边走。若小于节点的值则往左边走

二叉搜索树的搜索

1.从根节点开始查找,小于节点值则往左边,大于节点值则往右边。找到就返回

2.若遍历完都没有找到,即返回找不到

二叉搜索树的删除(重点)

1.删除叶子节点(既没有左右孩子),直接删除然后将其父亲节点的指针赋值为nullptr

2.删除只有一个孩子的节点,直接删除然后将孩子连接至父亲节点

3.删除有两个孩子的节点,不能直接删除。从这个节点出发寻找左子树的最大值(既最右节点)或者右子树的最小值(既最左节点)。将找到的值的赋值给要删除的节点,然后删除我们找到的节点,这样就能保证不会破坏二叉搜索树的性质。

补充:若删除根节点的话,要单独处理一下

代码实现

cpp 复制代码
template<class K>
struct BSNode
{
	K _val;
	BSNode<K>* _left;
	BSNode<K>* _right;

	BSNode(const K& key)
		:_val(key)
		, _left(nullptr)
		, _right(nullptr)
	{ }
};

template<class K>
class BSTree
{
	//typedef BSNode<K> Node;
	using Node = BSNode<K>;//新的重命名方式
public:

	void Insert(const K& key)//搜索二叉树的插入(不允许冗余)
	{
		Node* cur = _root;
		if (!cur)
		{
			_root = new Node(key);
		}
		else
		{
			Node* parent = cur;
			while (cur)
			{
				if (cur->_val < key)
				{
					parent = cur;
					cur = cur->_right;
				}
				else
				{
					parent = cur;
					cur = cur->_left;
				}
			}
			if (parent->_val < key)
			{
				parent->_right = new Node(key);
			}
			else if (parent->_val > key)
			{
				parent->_left = new Node(key);
			}
			else
				return;
		}
	}



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

	//搜索二叉树的删除
	void Erase(const K& key)
	{
		Node* cur = _root;
		Node* parent = cur;

		//先找到相应位置
		while (cur)
		{
			if (cur->_val < key)
			{
				parent = cur;
				cur = cur->_right;
			}
			else if (cur->_val > key)
			{
				parent = cur;
				cur = cur->_left;
			}
			else
				break;
		}
		if (!cur)
			return;

		//进行删除
		if (!cur->_left && !cur->_right)//没有孩子
		{
			if (cur == _root)//若删除根节点
			{
				delete _root;
				_root = nullptr;
			}
			else
			{
				if (parent->_left == cur)
					parent->_left = nullptr;
				else
					parent->_right = nullptr;
				delete cur;
				cur = nullptr;  // 显式置空
			}

		}
		else if (!cur->_left || !cur->_right)//有一个孩子
		{
			if (cur == _root)//若删除根节点
			{
				if (cur->_left)
				{
					_root = cur->_left;
					delete cur;
					cur = nullptr;  // 显式置空
				}
				else
				{
					_root = cur->_right;
					delete cur;
					cur = nullptr;  // 显式置空
				}
			}
			else
			{
				if (!cur->_left)
				{
					if (parent->_left == cur)
					{
						parent->_left = cur->_right;
						delete cur;
						cur = nullptr;  // 显式置空
					}
					else
					{
						parent->_right = cur->_right;
						delete cur;
						cur = nullptr;  // 显式置空
					}
				}
				else
				{
					if (parent->_left == cur)
					{
						parent->_left = cur->_left;
						delete cur;
						cur = nullptr;  // 显式置空
					}
					else
					{
						parent->_right = cur->_left;
						delete cur;
						cur = nullptr;  // 显式置空
					}
				}
			}
		}
		else//有两个孩子
		{
			//寻找左子树最大值(或右子树最小值)来替换cur
			Node* Replace = cur->_left;
			Node* Replacep = cur;
			while (Replace->_right)
			{
				Replacep = Replace;
				Replace = Replace->_right;
			}
			swap(Replace->_val, cur->_val);
			
			if(Replacep->_right == Replace)
				Replacep->_right = Replace->_left;
			else
				Replacep->_left = Replace->_left;
			
			delete Replace;
		}
	}


	void Inorder()//中序遍历
	{
		_Inorder(_root);
		cout << endl;
	}

private:

	void _Inorder(Node* root)//中序遍历
	{
		if (!root)
			return;

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

	Node* _root = nullptr;
};
相关推荐
Evand J36 分钟前
【MATLAB例程】基于USBL和DVL的线性回归误差补偿,对USBL和DVL导航数据进行相互补偿,提高定位精度,附代码下载链接
开发语言·matlab·线性回归·水下定位·usbl·dvl
Larry_Yanan2 小时前
QML学习笔记(四十二)QML的MessageDialog
c++·笔记·qt·学习·ui
爱喝白开水a2 小时前
LangChain 基础系列之 Prompt 工程详解:从设计原理到实战模板_langchain prompt
开发语言·数据库·人工智能·python·langchain·prompt·知识图谱
Neverfadeaway2 小时前
【C语言】深入理解函数指针数组应用(4)
c语言·开发语言·算法·回调函数·转移表·c语言实现计算器
武子康2 小时前
Java-152 深入浅出 MongoDB 索引详解 从 MongoDB B-树 到 MySQL B+树 索引机制、数据结构与应用场景的全面对比分析
java·开发语言·数据库·sql·mongodb·性能优化·nosql
杰克尼2 小时前
JavaWeb_p165部门管理
java·开发语言·前端
R-G-B2 小时前
【35】MFC入门到精通——MFC运行 不显示对话框 MFC界面不显示
c++·mfc·mfc运行 不显界面·mfc界面不显示
能不能别报错2 小时前
K8s学习笔记(十九) K8s资源限制
笔记·学习·kubernetes
一成码农2 小时前
JavaSE面向对象(下)
java·开发语言
Madison-No72 小时前
【C++】探秘vector的底层实现
java·c++·算法