二叉搜索树概念及实现

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

  • 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
  • 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
  • 它的左右子树也分别为二叉搜索树
    在这里插入图片描述
    二.二叉搜索树的操作

1.查找

  • 若根节点不为空:
  • 如果根节点key ==查找key,返回true
  • 如果根节点key<查找key,在它的右子树查找
  • 如果根节点key>查找key,在它的左子树查找
  • 否则,返回false

2.插入:

  • 如果树是空树,则直接进行插入

  • 否则,按照二叉搜索树的性质进行插入
    在这里插入图片描述
    如果在这棵树中要插入元素为7的新节点,则过程为:

  • 7大于根节点6,往根节点的右子树进行插入

  • 根节点变为8,7小于8,则往8的左子树进行插入

  • 8的左子树为空树,则直接进行插入

3.删除

  • 如果要删除的节点不在这棵树中则返回false
  • 如果要删除的节点只有左孩子节点,则让被删除节点的双亲节点指向被删除节点的左孩子节点
  • 如果要删除的节点只有右孩子节点,则让被删除节点的双亲节点指向被删除节点的右孩子节点
  • 如果要删除的节点有左右孩子节点,则要找它的替换节点后进行删除
    在这里插入图片描述
    如果要删除节点9,则让节点8的右子树指向节点10
    如果要删除节点7(有左右孩子节点),则用节点6来替代节点7,之后删除节点7

三.实现

#pragma once

template<class K,class V>
struct BSTreeNode
{
	BSTreeNode<K,V>* _left;
	BSTreeNode<K, V>* _right;
	std::pair<K, V> _kv;

	BSTreeNode(const std::pair<K, V>& kv)
		:_left(nullptr)
		, _right(nullptr)
		, _kv(kv)
	{}
};

template<class K,class V>
class BSTree
{
	typedef BSTreeNode<K, V> Node;
public:
	BSTree()
		:_root(nullptr)
	{}
	
	Node* Find(const K& k)
	{
		if (_root == nullptr)
			return NULL;
		Node* cur = _root;
		while (cur)
		{
			if (cur->_kv.first < k)
				cur = cur->_right;
			else if (cur->_kv.first>k)
				cur = cur->_left;
			else
			{
				 cout<<cur->_kv.first<<endl;
				 return cur;
			}
		}
		return NULL;
	}

	bool Insert(const std::pair<K, V>& kv)
	{
		if (_root == nullptr)
		{
			_root = new Node(kv);
			return true;
		}
		Node* cur = _root;
		Node* parent = _root;
		while (cur)
		{
			if (cur->_kv.first > kv.first)
			{
				parent = cur;
				cur = cur->_left;
			}
			else if (cur->_kv.first<kv.first)
			{
				parent = cur;
				cur = cur->_right;
			}
			else if (cur->_kv == kv)
			{
				return false;
			}
		}
		cur = new Node(kv);
		if (parent->_kv.first > kv.first)
			parent->_left = cur;
		else
			parent->_right = cur;
		return true;
	}

	bool Erase(const K& k)
	{
		if (_root == nullptr)
			return false;
		Node* cur = _root;
		Node* parent = _root;
		while (cur)
		{
			
			if (cur->_kv.first > k)
			{
				parent = cur;
				cur = cur->_left;
			}
			else if (cur->_kv.first < k)
			{
				parent = cur;
				cur = cur->_right;
			}
			else           //找到删除节点
			{
				Node* del = cur;
				if (!cur->_left)                    //左节点为空
				{
					if (parent == _root)
					{
						_root = cur->_right;
					}
					else
					{
						if (parent->_left == cur)
						{
							parent->_left = cur->_right;
						}
						else
						{
					
							parent->_right = cur->_right;
						}
					}
				}
				else if (!cur->_right)             //右节点为空
				{
					if (parent == _root)
					{
						_root = cur->_left;
					}
					else
					{
						if (parent->_left == cur)
						{
							parent->_left = cur->_left;
						}
						else
						{
							parent->_right = cur->_left;
						}
					}

				}
				else                       //左右节点都不为空
				{
					Node* prereplace=cur;
					Node* replace = cur->_right;
					while (replace->_left)
					{
						prereplace = replace;
						replace = replace->_left;
					}
					cur->_kv = replace->_kv;
					del = replace;

					//删除替代的最左节点
					if (prereplace->_left == replace)
					{
						prereplace->_left = replace->_right;
					}
					else
					{
						prereplace->_right = replace->_right;
					}	
				}
				delete del;
				return true;
			}		
		}
		return false;
	}

	void Inorder()
	{
		return _Inorder(_root);
	}

	void _Inorder(Node* root)
	{
		if (root == nullptr)
			return;
		_Inorder(root->_left);
		cout << root->_kv.first<<' ';
		_Inorder(root->_right);
	}
private:
	Node* _root;
};

void TestBSTree()
{
	int a[] = { 5, 3, 4, 1, 7, 8, 2, 6, 0, 9,0};
	BSTree<int, int> t;
	for (auto e : a)
	{
		t.Insert(std::make_pair(e, e));
	}
	t.Inorder();
	std::cout << std::endl;
	
	t.Erase(2);
	t.Erase(8);
	t.Erase(1);
	t.Erase(7);
	//t.Erase(2);
	t.Inorder();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值