BSTree——二叉搜索树

        二叉搜索树的两种模型,key模型和key/value模型,分别用与判断key是否存在和根据key查找对应value,二者再实现上相近,下面以key/value模型为例


二叉搜索树的原理

·二叉搜索树的左树中的所有节点都比根小

·右树中的的所有节点都比根大

·他的子树都满足上面两条

对以一个数据,通过与节点的大小比较,可以快速确定该数据再在树中应该所在的位置,从而判断该树中是否存在该数据或者找到该数据所对应的数据

例:插入5 2 9 6 1 


二叉搜索树的节点

二叉搜索树的节点与二叉树类似,包含分别指向左孩子和有孩子的指针,和_key、_value,用于存储记录的值。


二叉搜索树主要功能的实现

查找fInd

通过查找值的与节点key的大小关系对比如果比当前节点小则向左寻找,比当前节点大则向右寻找,等于当前节点则返回当前节点,如果最后遍历到空则说明树中没有对应值,返回空

Node* find(const K& key)
{
	Node* cur = _root;
	while (cur)
	{
		if (cur->_key > key)
		{
			cur = cur->_left;
		}
		else if (cur->_key < key)
		{
			cur = cur->_right;
		}
		else
		{
			return cur;
		}
	}
	return nullptr;
}

插入insert

insert的实现与find类似,首先在树中查找要插入的值,如果存在则取消插入,因为二叉搜索树的结构不允许其存在键值冗余,最后如果没有找到,遍历到一个空的节点,那么该位置就是插入值应该存在的位置,我们在该位置创建并插入一个节点。

Node* insert(const K& key, const V& value)
{
	if (_root == nullptr)
	{
		_root = new Node(key,value);
		return nullptr;
	}
	Node* cur = _root;
	Node* parent = nullptr;
	while (cur)
	{
		if (cur->_key < key)
		{
			parent = cur;
			cur = cur->_right;
		}
		else if (cur->_key > key)
		{
			parent = cur;
			cur = cur->_left;
		}
		else
		{
			return cur;
		}
	}
	cur = new Node(key,value);
	if (parent->_key < cur->_key)
	{
		parent->_right = cur;
	}
	else
	{
		parent->_left = cur;
	}
	return nullptr;
}

删除erase

erase是二叉搜索树中最难实现的部分,因为随意地删除某个节点,可能会导致二叉搜索树被破坏。首先与查找类,找到删除值的位置,同时为了方便删除节点,我们事先维护一个指针parent,找到被删结点的同时,找到该节点的父节点。

对于删除找到的节点(删除节点),我们分三种情况讨论:

1.删除节点的左子树为空

将删除节点的右子树替换删除节点与删除节点的父节点相连(如果删除节点是根节点,则直接把删除节点的右节点设置为根节点),然后释放节点

2.删除节点的右子树为空

与删除左子树类似,将删除节点的左孩子替换删除节点与删除节点的父节点相连(如果删除节点是根节点,则直接把删除节点的左节点设置为根节点),然后释放节点

3.删除节点的左右都不为空

要使删除后该节点位置仍然满足大于全部左子树,并且小于全部右子树,我们可以把左子树的最大值或者右子树的最小值给到删除节点的位置,再释放该节点

bool Erase(const K& key)
{
	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;
			}
			else if (cur->_right == nullptr)
			{
				if (cur == _root)
				{
					_root = cur->_left;
				}
				else
				{
					if (parent->_right = cur)
					{
						parent->_right = cur->_left;
					}
					else
					{
						parent->_left = cur->_right;
					}
				}
				delete cur;
			}
			else
			{
				parent = cur;
				Node* minRight = cur->_right;
				while (minRight->_left)
				{
					parent = minRight;
					minRight = minRight->_left;
				}

				cur->_key = minRight->_key;
				if (parent->_right = minRight)
				{
					minRight->_right = parent->_right;
				}
				else
				{
					minRight->_left = parent->_right;
				}
				delete minRight;
			}
			return true;
		}
	}
	return false;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值