二叉搜索树

概念

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

特性

1、最左侧的节点一定是所有节点中最小的,最右侧的节点一定是所有节点中最大的
2、中序遍历是有序的

二叉搜索树的操作

查找

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

插入

1、树为空,则直接插入
2、树不为空,按二叉搜索树性质查找插入节点位置,插入新节点

删除

首先查找元素是否在二叉搜索树中,如果不存在,则返回,否则要删除的节点可能分以下几种情况
        a). 要删除的节点无孩子节点
        b). 要删除的节点只有左孩子节点
        c). 要删除的节点只有右孩子节点
        d). 要删除的节点有左、右孩子节点
上面四种情况,在实际考虑时可以将情况a与情况b或者情况c合并起来,因此真正删除情况如下:
        情况b:删除该节点且使被删除节点的双亲节点指向被删除节点的左孩子节点
        情况b:删除该节点且使被删除节点的双亲节点指向被删除节点的右孩子节点
        情况d:在它的右子树中寻找中序下的第一个节点(关键码最小),用它的值填补到被删除节点中,再来处理该节点的删除问题

模拟实现

#include <iostream>
using namespace std;

//为了简化问题,将二叉搜索树定义为节点值都不相同的树

template<class  T>
struct BSTNode
{
	BSTNode(const T& data = T())
		: _pLeft(nullptr)
		, _pRight(nullptr)
		, _data(data)
	{}
	BSTNode<T>* _pLeft;
	BSTNode<T>* _pRight;
	T _data;
};

template<class T>
class BSTree
{
	typedef BSTNode<T> Node;
	typedef Node* PNode;

public:
	BSTree()
		:_pRoot(nullptr)
	{}

	~BSTree()
	{}

	PNode Find(const T& data)
	{
		if (nullptr == _pRoot)
		{
			return nullptr;
		}
		PNode pCur = _pRoot;
		while (pCur)
		{
			if (data == pCur->_data)
			{//找到了
				return pCur;
			}
			else if (data < pCur->_data)
			{
				pCur = pCur->_pLeft;
			}
			else
			{
				pCur = pCur->_pRight;
			}
		}
		//未找到
		return nullptr;  
	}

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

	PNode LeftMost()
	{
		if (_pRoot)
		{
			PNode pCur = _pRoot;
			while (pCur->_pLeft)
			{
				pCur = pCur->_pLeft;
			}
			return pCur;
		}
		return nullptr;
	}

	PNode RightMost()
	{
		if (_pRoot)
		{
			PNode pCur = _pRoot;
			while (pCur->_pRight)
			{
				pCur = pCur->_pRight;
			}
			return pCur;
		}
		return nullptr;
	}

	bool Insert(const T& data)
	{
		if (!_pRoot)
		{
			_pRoot = new Node(data);
			return true;
		}

		PNode pCur = _pRoot;
		PNode pParent = nullptr;
		while (pCur)
		{
			pParent = pCur;
			if (data < pCur->_data)
			{
				pCur = pCur->_pLeft;
			}
			else if (data > pCur->_data)
			{
				pCur = pCur->_pRight;
			}
			else
			{//有重复项,插入失败
				return false;
			}
		}

		pCur = new Node(data);
		if (data < pParent->_data)
		{
			pParent->_pLeft = pCur;
		}
		else
		{
			pParent->_pRight = pCur;
		}
		return true;
	}

	bool Delete(const T& data)
	{
		if (!_pRoot)
		{
			return false;
		}
		PNode pCur = _pRoot;
		PNode pParent = nullptr;
		while (pCur)
		{
			if (data == pCur->_data)
			{
				break;
			}
			else if (data < pCur->_data)
			{
				pParent = pCur;
				pCur = pCur->_pLeft;
			}
			else
			{
				pParent = pCur;
				pCur = pCur->_pRight;
			}
		}
		if (nullptr == pCur)
		{
			return false;
		}

		PNode pDeleteNode = pCur;
		if (nullptr == pCur->_pRight)
		{//叶子节点和只有左孩子的节点
			if (nullptr == pParent)
			{
				_pRoot = pCur->_pRight;
			}
			else
			{
				if (pParent->_pLeft == pCur)  //data<pParent->_data
				{//待删节点是父节点的左节点
					pParent->_pLeft = pCur->_pLeft;
				}
				else
				{
					pParent->_pRight = pCur->_pLeft;
				}
			}
		}
		else if (nullptr == pCur->_pLeft)
		{//只有右孩子的节点
			if (nullptr == pParent)
			{
				_pRoot = pCur->_pLeft;
			}
			else
			{
				if (pParent->_pLeft == pCur)  //data<pParent->_data
				{//待删节点是父节点的左节点
					pParent->_pLeft = pCur->_pRight;
				}
				else
				{
					pParent->_pRight = pCur->_pRight;
				}
			}
		}
		else
		{//左右孩子都存在
			PNode pDelete = pCur->_pRight;
			pParent = pCur;
			while (pDelete->_pLeft)
			{
				pParent = pDelete;
				pDelete = pDelete->_pLeft;
			}

			pCur->_data = pDelete->_data;

			if (pParent->_pLeft == pDelete)
				pParent->_pLeft = pDelete->_pRight;
			else
				pParent->_pRight = pDelete->_pRight;

			pDeleteNode = pDelete;

		}

		return true;
	}

private:
	void _InOrder(PNode pRoot)
	{
		if (pRoot)
		{
			_InOrder(pRoot->_pLeft);
			cout << pRoot->_data << " ";
			_InOrder(pRoot->_pRight);
		}
	}

private:
	PNode _pRoot;
};

void TestBSTree()
{
	BSTree<int> tree;

	int a[] = { 9, 6, 4, 8, 2, 3, 1, 0, 7, 5 };
	for (auto e : a)
		tree.Insert(e);

	tree.InOrder();

	cout << tree.LeftMost()->_data << endl;
	cout << tree.RightMost()->_data << endl;

	tree.Delete(0);
	tree.InOrder();

	tree.Delete(5);
	tree.InOrder();

	tree.Delete(9);
	tree.InOrder();
}

int main()
{
	TestBSTree();
	return 0;
}

性能分析

最优情况下,二叉搜索树为完全二叉树,其查找效率为:O(log2N)
最差情况下,二叉搜索树退化为单支树,其查找效率为:O(N)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值