数据结构-二叉树-二叉搜索树

一、概念

二叉搜索树又称二叉排序树,它或者是一棵空树,或者具有以下性质的二叉树:

若它的左子树不为空,则左树上所有节点的值都小于根节点的值。

若它的右子树不为空,则右子树上所有节点的值都大于根节点的值。

它的左右子树也分别为二叉搜索树。最多找O(N)。

二、查找、插入、删除

插入

cpp 复制代码
bool Insert(K& k)
{
	
	if (_root == nullptr)
	{
		_root = new BSNode(k);
		return true;
	}
	BSNode* cur = _root;
	BSNode* parent = nullptr;
	while (cur)
	{
		if (cur->_k < k)
		{
			parent = cur;
			cur = cur->_right;
		}
		else if (cur->_k > k)
		{
			parent = cur;
			cur = cur->_left;
		}
	}
	if (parent->_k < k)
	{
		parent->_right = new BSNode(k);
	}
	else if (parent->_k > k)
	{
		parent->_left = new BSNode(k);
	}
	else
	{
		return false;
	}
	return true;
}

查找

cpp 复制代码
bool Find(K k)
{
	BSNode* cur = _root;
	while (cur)
	{
		if (cur->_k < k)
		{
			cur = cur->_right;
		}
		else if (cur->_k > k)
		{
			cur = cur->_left;
		}
		else
		{
			return true;
		}
	}
	return false;
}

删除

依次删除7、14、3、8。7和14属于直接删除的场景

3、8属于需要替换法进行删除的场景。

1、没有孩子

2、一个孩字

3、两个孩子,需要进行替换,也就是替换法,用左子树的最大节点或者右子树的最小节点。

最大节点为最右节点,最小节点就是最左节点 ,还需要处理要删除的节点为根节点,它没有左子树或者没有右子树的情况。

还有一种情况就是leftmax就是root的左子树的根,此时parent为nullptr所以我们需要让parent = cur

cpp 复制代码
void Erase(K& k)
{
	BSNode* cur = _root;
	BSNode* parent = nullptr;
	while (cur)
	{
		if (cur->_k < k)
		{
			parent = cur;
			cur = cur->_right;
		}
		else if (cur->_k > k)
		{
			parent = cur;
			cur = cur->_left;
		}
		else
		{
			//开始托孤
			//要删除的节点,左孩子为空
			if (cur->_left == nullptr)
			{
				//需要判断删除节点就是根节点的情况
				if (cur == _root)
				{
					_root = cur->_right;
				}
				else
				{
					if (parent->_right == cur)
					{
						parent->_right = cur->_right;
					}
					else
					{
						parent->_left = cur->_right;
					}
				}
				
			}
			else if (cur->_right == nullptr)
			{
				if (cur == _root)
				{
					_root = cur->_left;
				}
				else
				{
					if (parent->_right == cur)
					{
						parent->_right = cur->_left;
					}
					else 
					{
						parent->_left = cur->_left;
					}
				}
			}
			else //两个孩子的情况,就需要替代法来删除
			{
				//找到左子树中最大的节点
				BSNode* leftMax = cur->_left;
				//注意为什么这里等于cur;
				BSNode* parent = cur;  
				while (leftMax->_right)
				{
					parent = leftMax;
					leftMax = leftMax->_right;
				}
				//找到以后把删除节点和leftmax节点的值做交换
				std::swap(cur->_k, leftMax->_k);

				//我们该把父亲的那个孩子和cur节点的孩子连接起来呢需要判断
				if (parent->_left == leftMax)
				{
					parent->_left = leftMax->_left;
				}
				else
				{
					parent->_right = leftMax->_left;
				}

				cur = leftMax;
			}

			delete cur;
			cur = nullptr;
		}
	}
}

有序数组:二分查找,问题:插入删除效率不行

二叉搜索树:插入删除效率还行。

如果退化成下面的情况,插入删除的效率就变成了O(N),所以我们引出了AVL树红黑树B树系列。

接下来我们看一下递归版本的删除,插入和发现

cpp 复制代码
bool _EraseR(BSNode*& root, const K& k)
{
	
	if (root == nullptr)
	{
		return false;
	}
	if (root->_k < k)
	{
		_EraseR(root->_right, k);
	}
	else if (root->_k > k)
	{
		_EraseR(root->_left, k);
	}
	else
	{
		BSNode* del = root;
		if (root->_left == nullptr)
		{
			root = root->_right;
		}
		else if (root->_right == nullptr)
		{
			root = root->_left;
		}
		else
		{
			BSNode* leftMax = root->_left;
			while (leftMax->_right)
			{
				leftMax = leftMax->_right;
			}
			std::swap(leftMax->_k, root->_k);

			return _EraseR(root->_left, k);
		}
		delete del;
		del = nullptr;
		return true;
	}
}
bool _InsertR(BSNode*& root,const K& k)
{
	if (root == nullptr)
	{
		root = new BSNode(k);
		return true;
	}
	if (root->_k < k)
	{
		_InsertR(root->_right, k);
	}
	else if (root->_k > k)
	{
		_InsertR(root->_left, k);
	}
	else
	{
		return false;
	}
}
bool _FindR(BSNode* root, const K& k)
{
	if (root == nullptr)
		return false;
	BSNode* cur = root;
	if (cur->_k < k)
	{
		_FindR(root->_right, k);
	}
	else if (cur->_k > k)
	{
		_FindR(root->_left, k);
	}
	else
	{
		return true;
	}
}
相关推荐
稚南城才子,乌衣巷风流2 小时前
动态开点:原理、实现与应用场景
数据结构·算法
yyds_yyd_100862 小时前
1464. 数组中两元素的最大乘积(2026.07.27)
数据结构·c++·算法·leetcode
白白白小纯8 小时前
算法篇—返回倒数第k个节点
c语言·数据结构·算法·leetcode
无忧.芙桃8 小时前
数据结构之堆
c语言·数据结构·c++·算法·
小蒋学算法8 小时前
算法-删除元素后最大固定点数目-典型最长增长序列算法
数据结构·算法
白白白小纯10 小时前
算法篇—链表的中间节点
c语言·数据结构·算法·leetcode
pluviophile_s11 小时前
数据结构:第6讲:树与二叉树
数据结构·笔记
来一碗刘肉面12 小时前
字符串模式匹配(朴素模式匹配算法与KMP算法)
数据结构·算法
code bean1 天前
【C#】 `Channel<T>` 深度解析:生产者-消费者模式的现代解法
数据结构·c#
storyseek1 天前
前缀和实现Kogge-Stone算法
数据结构·算法