_cpp二叉搜索树

1 理解二叉搜索树

1.1 二叉搜索树概念

  • 二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树:
    • 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值。
    • 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值。
    • 它的左右子树也分别为二叉搜索树。

在这里插入图片描述
在这里插入图片描述

1. 二叉搜索树的查找

a、从根开始比较,查找,比根大则往右边走查找,比根小则往左边走查找。
b、最多查找高度次,走到到空,还没找到,这个值不存在。

2. 二叉搜索树的插入

插入的具体过程如下:
a. 树为空,则直接新增节点,赋值给root指针
b. 树不空,按二叉搜索树性质查找插入位置,插入新节点

在这里插入图片描述

3. 二叉搜索树的删除

  • 首先查找元素是否在二叉搜索树中,如果不存在,则返回, 否则要删除的结点可能分下面四种情
    况:
    a. 要删除的结点无孩子结点
    b. 要删除的结点只有左孩子结点
    c. 要删除的结点只有右孩子结点
    d. 要删除的结点有左、右孩子结点
  • a可以与情况b或者c合并起来,因此真正的删除过程
    如下:
    情况b:删除该结点且使被删除节点的双亲结点指向被删除节点的左孩子结点–直接删除
    情况c:删除该结点且使被删除节点的双亲结点指向被删除结点的右孩子结点–直接删除
    情况d:在它的右子树中寻找中序下的第一个结点(关键码最小),用它的值填补到被删除节点
    中,再来处理该结点的删除问题–替换法删除
    int a[] = {8, 3, 1, 10, 6, 4, 7, 14, 13};
    在这里插入图片描述

二叉搜索树实现

namespace Key
{
	template<class T>
	struct BSTNode
	{
		BSTNode(const T& data = T())
			:_pleft(nullptr)
			, _pright(nullptr)
			, _data(data)
		{}

		BSTNode* _pleft;
		BSTNode* _pright;
		T _data;
	};

	template<class T>
	class BSTree
	{
		typedef BSTNode<T> Node;
	public:

		bool Insert(const T& key)
		{
			if (_root == nullptr)
			{
				_root = new Node(key);
				return true;
			}

			Node* cur = _root;
			Node* parent = _root;
			while (cur)  //迭代并去重
			{
				if (cur->_data < key)
				{
					parent = cur;
					cur = cur->_pright;
				}
				else if (cur->_data > key)
				{
					parent = cur;
					cur = cur->_pleft;
				}
				else
				{
					return false;
				}
			}

			cur = new Node(key);
			if (parent->_data < key)
			{
				parent->_pright = cur;
			}
			else  //此处不可能相等 <
			{
				parent->_pleft = cur;
			}

			return true;
		}

		bool Find(const T& key)
		{
			Node* cur = _root;
			while (cur)
			{
				if (cur->_data < key)
				{
					cur = cur->_pright;
				}
				else if (cur->_data > key)
				{
					cur = cur->_pleft;
				}
				else
				{
					return true;
				}
			}

			return false;
		}

		bool Erase(const T& key)
		{
			if (_root == nullptr)
			{
				return false;
			}

			Node* parent = _root;
			Node* cur = _root;
			while (cur)
			{
				if (cur->_data < key)
				{
					parent = cur;
					cur = cur->_pright;
				}
				else if (cur->_data > key)
				{
					parent = cur;
					cur = cur->_pleft;
				}
				else
				{
					//开始删除 1. 左为空 2. 右为空 3. 左右都不为空
					if (cur->_pleft == nullptr)
					{
						if (cur == _root)
						{
							_root = cur->_pright;
						}
						else
						{
							if (cur == parent->_pleft)
							{
								parent->_pleft = cur->_pright;
							}
							else
							{
								parent->_pright = cur->_pright;
							}
						}

						delete cur;
						cur = nullptr;
					}
					else if (cur->_pright == nullptr)
					{
						if (cur == _root)
						{
							_root = cur->_pleft;
						}
						else
						{
							if (cur == parent->_pleft)
							{
								parent->_pleft = cur->_pleft;
							}
							else
							{
								parent->_pright = cur->_pleft;
							}
						}

						delete cur;
						cur = nullptr;
					}
					else
					{
						//找右子树最小值,进行替换
						Node* minparent = cur;
						Node* min = cur->_pright;
						while (min->_pleft)
						{
							minparent = min;
							min = min->_pleft;
						}

						swap(cur->_data, min->_data);
						//可能删除的结点右面有结点以及删除结点的位置
						if (minparent->_pleft == min)
						{
							minparent->_pleft = min->_pright;
						}
						else
						{
							minparent->_pright = min->_pright;
						}

						delete min;
						min = nullptr;
					}

					return true;
				}
			}

			return false;
		}

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

		BSTree()
		{}
		
		~BSTree()
		{
			_Destory(_root);
		}

	private:
		void _Destory(Node*& root)
		{
			if (root == nullptr)
			{
				return;
			}

			_Destory(root->_pleft);
			_Destory(root->_pright);
			delete root;
			root = nullptr;
		}


		Node* _root = nullptr;
	};
}

void TestBsTree1()
{
	Key::BSTree<int> t;
	int a[] = { 8, 3, 1, 10, 4, 6, 7, 14, 13, 4, 3, 4 };
	for (auto e : a)
	{
		t.Insert(e);
	}

	//排序+去重
	t.InOrder();

	t.Erase(3);
	t.InOrder();

	t.Erase(10);
	t.InOrder();

	for (auto e : a)
	{
		t.Erase(e);
		t.InOrder();
	}

}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

昨天;明天。今天。

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值