数据结构——二叉搜索树

作者:小 琛
欢迎转载,请标明出处

引言

二叉树是数据结构中的一个常见结构,而二叉搜索树则是一种特殊的二叉树,是高阶数据结构(如AVL树、红黑树)的基础。

二叉树的特点

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

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

平衡二叉树的几个重要操作

查找

1.若树为空,则返回nullptr。
2.不为空,则看下图:
在这里插入图片描述

插入
  1. 当树为空即该节点为该树的第一个节点,直接插入
  2. 当树不为空,定义一个临时节点cur,cur从根节点开始;定义一个father节点,用来记录父节点。比较该插入节点的值和当前节点的值,若大则右树寻找,小则左树寻找,father节点同样移动。
  3. 当cur为空时,则为该插入的地方。将此时father节点的信息进行更新。

在这里插入图片描述

删除

在二叉搜索树中,如果不存在,则返回, 否则要删除的结点可能分下面四种情况:
a. 要删除的结点无孩子结点
b. 要删除的结点只有左孩子结点
c. 要删除的结点只有右孩子结点
d. 要删除的结点有左、右孩子结点

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

情况b:删除该结点且使被删除节点的双亲结点指向被删除节点的左孩子结点
情况c:删除该结点且使被删除节点的双亲结点指向被删除结点的右孩子结点
情况d:在它的右子树中寻找中序下的第一个结点(关键码最小),用它的值填补到被删除节点中,再来处理该结点的删除问题

#pragma once;

#include <iostream>
using namespace std;
template <class T>
struct BSTreeNode
{
	BSTreeNode<T>* _left;
	BSTreeNode<T>* _right;
	T _key;

	BSTreeNode(const T& key)
		:_left(nullptr)
		, _right(nullptr)
		, _key(key)
	{}
};

template <class T>
class BSTree
{
	typedef BSTreeNode<T> Node;
public:
	BSTree()
		:_root(nullptr)
	{}
	~BSTree()
	{}
	bool Insert(const T& key)
	{
		if (_root == nullptr)
		{
			_root = new Node(key);
			return true;
		}
		Node* cur = _root;
		Node* father = nullptr;
		while (cur)
		{
			if (cur->_key < key)//左树寻找
			{
				father = cur;
				cur = cur->_left;
			}
			else if (cur->_key>key)//右树寻找
			{
				father = cur;
				cur = cur->_right;
			}
			else//已经有该节点,插入失败
				return false;
		}
		Node* newnode = new Node(key);
		if (father->_key < key)
		{
			father->_right = newnode;
		}
		else
		{
			father->_left = newnode;
		}
		return true;
	}
	Node* Find(const T& key)
	{
		if (_root == nullptr)
		{
			return nullptr;
		}
		Node* cur = _root;
		while (cur)
		{
			if (cur->_key == key)
				return cur;
			else if (cur->_key < key)
			{
				cur = cur->_right;
			}
			else
			{
				cur = cur->_left;
			}
		}
		return nullptr;
	}

	bool Erase(const T& key)
	{
		Node* parent = nullptr;
		Node* cur = _root;
		while (cur)
		{
			if (cur->_key < key)
			{
				parent = cur;
				cur = cur->_right;
			}
			else if (cur->_key > key)
			{
				parent = cur;
				cur = cur->_left;
			}
			else
			{
				// 1.左为空
				// 2.右为空
				// 3.左右都不为空
				if (cur->_left == nullptr)
				{
					if (parent == nullptr)
					{
						_root = cur->_right;
					}
					else
					{
						if (cur == parent->_left)
							parent->_left = cur->_right;
						else
							parent->_right = cur->_right;
					}

					delete cur;
				}
				else if (cur->_right == nullptr)
				{
					if (parent == nullptr)
					{
						_root = cur->_left;
					}
					else
					{
						if (cur == parent->_left)
							parent->_left = cur->_left;
						else
							parent->_right = cur->_left;
					}

					delete cur;
				}
				else
				{
					// 替换法删除  左树的最大节点(最右节点) 或者是右树的最小节点(最左节点)
					Node* minNodeParent = cur;  // 这里要注意不能初始化给空
					Node* minNode = cur->_right;
					while (minNode->_left)
					{
						minNodeParent = minNode;
						minNode = minNode->_left;
					}

					swap(cur->_key, minNode->_key);
					// 转换成删除minNode

					// 因为minNode是作为空的节点,可以直接删除
					if (minNodeParent->_right == minNode)
						minNodeParent->_right = minNode->_right;
					else
						minNodeParent->_left = minNode->_right;

					delete minNode;
				}

				return true;
			}
		}

		return false;
	}
private:
	Node* _root = nullptr;
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值