二叉搜索树的实现代码及思路

文章目录


在这里插入图片描述


template<class K,class V>
class BSTreeNode
{
public:
	BSTreeNode<K,V>* left;
	BSTreeNode<K,V>* right;
	K _key;
	V _value;

	BSTreeNode(const K& key,const V& value)
		:left(nullptr)
		,right(nullptr)
		,_key(key)
		,_value(value)
	{}
};

template<class K, class V>
class BSTree
{
	typedef BSTreeNode<K, V> Node;
public:
	bool Insert(const K& key, const V& value)
	{
		if (_root == nullptr)
		{
			_root = new Node(key,value);
			return true;
		}

		Node* cur = _root;
		Node* parent = nullptr;

		//走到这说明已经有了根,就开始从根找,左大右小
		while (cur)
		{
			parent = cur;
			if (key < cur->_key)
			{
				cur = cur->left;
			}
			else if (key > cur->_key)
			{
				cur = cur->right;
			}
			else
			{
				return false;
			}
		}

		//走到这说明已经找到结点应在位置,现在只需要判断父子关系然后插入
		cur = new Node(key,value);
		if (key>parent->_key)
		{
			parent->right= cur;
		}
		else
		{
			parent->left = cur;
		}
		return true;
	}
	Node* Find(const K& key)
	{
		Node* cur = _root;
		while (cur)
		{
			if (key < cur->_key)
			{
				cur = cur->left;
			}
			else if (key > cur->_key)
			{
				cur = cur->right;
			}
			else
			{
				return cur;
			}
		}
		return nullptr;
	}

	bool Erase(const K& key)
	{
		//删除前先让cur走到被删除结点
		Node* cur = _root;
		Node* parent = nullptr;

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

				//走到这里表明已经找到该结点
				//这里既包含只有右孩子又包含没有孩子两种情况,具体下面细看
				if (cur->left == nullptr)
				{
					//左孩子为空两种情况
					//1.cur为根结点,直接将根指向它的孩子
					if (cur == _root)
					{
						//没有孩子则让_root指向空,因为构造函数已经让这些指针指向nullptr
						_root = cur->right;
					}
					//2.cur为普通结点
					else
					{
						//让cur的右孩子继承cur的位置并删除cur
						//这里暂时不知cur与p的关系,先判断
						if (cur == parent->left)
						{
							//当没有孩子时,这里指向nullptr,符合正常逻辑
							parent->left = cur->right;
						}
						else
						{
							parent->right = cur->right;
						}
					}
					delete cur;
				}
				//这里也隐藏地解决了没有孩子结点的情况,详情如上
				else if (cur->right == nullptr)
				{
					//1.当前结点为根结点
					if (cur == _root)
					{
						_root = cur->left;
					}
					else
					{
						//判断cur与parent关系
						if (cur == parent->left)
						{
							parent->left = cur->left;
						}
						else
						{
							parent->right = cur->left;
						}
					}
					delete cur;
				}
				//既有左孩子又有右孩子
				//解决思路就是找个与cur值大小最接近的,即cur结点左数的最右结点/右数的最左结点
				//这里默认用右树的最左结点
				else
				{
					Node* subleft = cur->right;
					Node* subleft_p = cur;

					while (subleft->left)
					{
						subleft_p = subleft;
						subleft = subleft->left;
					}

					//已经找到与cur最接近数字,交换两者key、value值
					swap(cur->_key, subleft->_key);
					swap(cur->_value, subleft->_value);

					//准备删除subleft,有以下几点考虑要素
					//1.有无孩子,不可能有左孩子但可能有右孩子
					//2.有无可能是根结点,不可能

					//判断subleft与subleft_p的关系
					if (subleft == subleft_p->left)
					{
						subleft_p->left = subleft->right;
					}
					else
					{
						subleft_p->left = subleft->right;
					}
					delete subleft;
				}
				return true;
			}
		}
	}
	void _InOrder(Node* root)
	{
		if (root == nullptr)
			return;

		_InOrder(root->left);
		cout << "key:" << root->_key << " value:" << root->_value << endl;
		_InOrder(root->right);
	}
	void InOrder()
	{
		_InOrder(_root);
		cout << endl;
	}
private:
	Node* _root = nullptr;
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值