【数据结构】搜索二叉树

一.搜索二叉树

1.1搜索二叉树的概念

搜索二叉树又叫排序二叉树,搜索二叉树可以为空,如果不为空应满足以下条件。
若它的左子树不为空,则左子树上所有节点的值都小于根节点的值

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

它的左右子树也分别为二叉搜索树

1.2 二叉搜索树操作

1.2.1搜索二叉树的查找

a、从根开始比较,查找,比根大则往右边走查找,比根小则往左边走查找。

b、最多查找高度次,走到到空,还没找到,这个值不存在。

1.2.2搜索二叉树的插入

a、从根开始如果根为空,就新建节点赋值给根的指针

b、根不为空就按照搜索二叉树的性质找到插入的位置,插入新的节点

1.2.3搜索二叉树的删除

首先查找元素是否在二叉搜索树中,如果不存在,则返回, 否则要删除的结点可能分下面四种情 况:

a. 要删除的结点无孩子结点

b. 要删除的结点只有左孩子结点

c. 要删除的结点只有右孩子结点

d. 要删除的结点有左、右孩子结点

看起来有待删除节点有4中情况,实际情况a可以与情况b或者c合并起来,因此真正的删除过程如下:

情况b:删除该结点且使被删除节点的双亲结点指向被删除节点的左孩子结点--直接删除

情况c:删除该结点且使被删除节点的双亲结点指向被删除结点的右孩子结点--直接删除

情况d:在它的右子树中寻找中序下的第一个结点(关键码最小),用它的值填补到被删除节点 中,再来处理该结点的删除问题--替换法删除

二.搜索二叉树的实现

template<class K>
struct Node
{
	struct Node<K>* left;
	struct Node<K>* right;
	K _key;
	Node(const K& key)
		:left(nullptr)
		,right(nullptr)
		,_key(key)
	{}
};


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

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

	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 (nullptr == cur->left)
				{
					if (cur == _root)
					{
						_root = cur->right;
					}
					else
					{
						if (parent->left == cur)
						{
							parent->left = cur->right;
						}
						else
						{
							parent->right = cur->right;
						}
					}
					
				}
				else if (nullptr == cur->right)
				{
					if (cur == _root)
					{
						_root = cur->left;
					}
					else
					{
						if (parent->left == cur)
						{
							parent->left = cur->left;
						}
						else
						{
							parent->right = cur->left;
						}
					}
					
				}
				else
				{
					node* parent = cur;
					node* sub_right_min = cur->right;
					while (sub_right_min->left)
					{
						parent = sub_right_min;
						sub_right_min = sub_right_min->left;
					}
					swap(sub_right_min->_key, cur->_key);
					if (parent->left == sub_right_min)
					{
						parent->left = sub_right_min->right;
					}
					else
					{
						parent->right = sub_right_min->right;
					}

				}
				return true;
			}
		}
		return false;
	}

	void InOrder()
	{
		_InOrder(_root);
		cout << endl;
	}

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


	bool EraseR(const K& key)
	{
		return _EraseR(_root,key);
	}
	
	bool InsertR(const K& key)
	{
		return _InsertR(_root, key);
	}
private:

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

	bool _EraseR(node*& root, const K& key)
	{
		if (root == nullptr)
		{
			return false;
		}
		if (root->_key > key)
		{
			return _EraseR(root->left,key);
		}
		else if (root->_key < key)
		{
			return _EraseR(root->right,key);
		}
		else
		{
			if (root->left == nullptr)
			{
				node* del = root;
				root = root->right;
				delete del;
			}
			else if (root->right == nullptr)
			{
				node* del = root;
				root = root->left;
				delete del;
			}
			else
			{
				node* sub_right_min = root->right;
				while (sub_right_min->left)
				{
					sub_right_min = sub_right_min->left;
				}
				swap(root->_key, sub_right_min->_key);
				return  _EraseR(root->right, key);
			}
		}
	}

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


	void _InOrder(node* root)
	{
		if (nullptr == root)
		{
			return;
		}
		_InOrder(root->left);
		cout<<root->_key<<" ";
		_InOrder(root->right);
	}

private:

	node* _root = nullptr;
};

三.搜索二叉树的性能分析

搜索二叉树用的最多的应该就是查找了,所以可以用查找来代表搜索二叉树的性能

最优情况,搜索二叉树是完全二叉数:时间复杂度就是log₂N。

最坏情况,搜索二叉树为单支树:时间复杂度是N²

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值