数据结构--二叉搜索树

本文介绍了二叉搜索树的基本概念,包括其定义和特性,并详细阐述了插入、查找和删除这三种基本操作。讨论了不同情况下二叉搜索树的性能,指出在最佳情况下平均查找长度为O(logn),而最坏情况下为O(n)。
摘要由CSDN通过智能技术生成

概念:

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

1、若它的左子树不为空,则左子树上所有节点的值都小于根节点的值

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

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

如下图:

 

二叉树基本操作

 

1.      插入:

在二叉查找树中插入新结点,要考虑以下步骤:

1.若二叉查找树root为空,则新结点为根;

2.若二叉查找树root不为空,则应该寻找插入点并返回它的地址(若新结点中的关键字已经存在,则返回空指针);

3.若新结点的关键字小于插入点的关键字,则将新结点插入到插入点的左子树中,大于则插入到插入点的右子树中。 

 

2.      查找

看key值,key值比当前结点值大在右中找,否则在左中查找。


3.      删除

删除分为几种情况

由此 我们可以写出代码:

template <class K,class V>
struct BSTNode
{
	BSTNode<K, V>* _pLeft;
	BSTNode<K, V>* _pRight;
	K _key;
	V _value;

	BSTNode(const K& key, const V& value)
		: _pLeft(NULL)
		, _pRight(NULL)
		, _key(key)
		, _value(value)
	{}
};

template<class K,class V>
struct BinaryTreeSearch
{
	typedef BSTNode<K, V> Node;
public:
	BinaryTreeSearch()
		:_pRoot(NULL)
	{}

	void Insert(const K& key, const V& value)
	{
		//头结点是空
		if (NULL == _pRoot)
		{
			_pRoot = new Node(key, value);
			return ;
		}

		Node* pCur = _pRoot;
		Node* pParent = NULL;
		//找插入位置
		while (pCur)
		{
			if (key > pCur->_key)
			{
				pParent = pCur;
				pCur = pCur->_pRight;
			}
			else if (key <= pCur->_key)
			{
				pParent = pCur;
				pCur = pCur->_pLeft;
			}
		}

		//插入元素
		if (key < pParent->_key)
			pParent->_pLeft = new Node(key, value);
		else
			pParent->_pRight = new Node(key,value);
	}
	
	bool Find(const K& key)
	{
		Node* pCur = _pRoot;
		//找插入位置
		while (pCur)
		{
			if (key > pCur->_key)
			{
				pCur = pCur->_pRight;
			}
			else if (key < pCur->_key)
			{
				pCur = pCur->_pLeft;
			}
			else
				return true;
		}
		return false;
	}

	bool Remove(const K& key)
	{
		Node* pCur = _pRoot;
		Node* pParent = NULL;
	
		//找位置
		while (pCur && pCur->_key != key)
		{
			if (key > pCur->_key)
			{
				pParent = pCur;
				pCur = pCur->_pRight;
			}
			else if (key <= pCur->_key)
			{
				pParent = pCur;
				pCur = pCur->_pLeft;
			}
		}

		if (pCur)
		{
			if (pCur != _pRoot && pCur->_pLeft == NULL || pCur->_pRight == NULL)
			{
				if (pCur->_pLeft == NULL)
				{
					if (pParent->_pLeft == pCur)
						pParent->_pLeft = pCur->_pRight;
					else
						pParent->_pRight = pCur->_pRight;

					delete pCur;
				}
				else if (pCur->_pRight == NULL)
				{
					if (pParent->_pRight = pCur)
						pParent->_pRight = pCur->_pLeft;
					else
						pParent->_pLeft = pCur->_pLeft;

					delete pCur;
				}
			}
			//如果这个节点左右都有孩子 此时应该找右边子树的最小结点 (即右子树最左边的结点)
			else
			{
				Node* pFirstInorder = pCur->_pRight;

				while (pFirstInorder->_pLeft)
				{
					pParent = pFirstInorder;
					pFirstInorder = pFirstInorder->_pLeft;
				}

				pCur->_key = pFirstInorder->_key;
				pCur->_value = pFirstInorder->_value;

				//如果不是右单只 说明pParent左有元素
				if (pParent->_pLeft == pFirstInorder)
					pParent->_pLeft = pFirstInorder->_pRight;
				else//是右单只
					pParent->_pRight = pFirstInorder->_pRight;

				pCur = pFirstInorder;
				delete pCur;
			}
		}

		if (pCur == NULL)
			return false;
		return true;
	}

private: 
	Node* _pRoot;
};

void Funtest()
{
	BinaryTreeSearch<int, int> bt;
	int a[] = { 5, 3, 4, 1, 7, 8, 2, 6, 0, 9 };
	bt.Insert(5, 5);
	bt.Insert(3, 3);
	bt.Insert(4, 4);
	bt.Insert(1, 1);
	bt.Insert(7, 7);
	bt.Insert(8, 8);
	bt.Insert(2, 2);
	bt.Insert(6, 6);
	bt.Insert(0, 0);
	bt.Insert(9, 9);

	cout << bt.Find(1) << endl;
	cout << bt.Find(111) << endl;

	bt.Remove(3);
}

二叉搜索树的性能分析:

插入和删除操作的主体部分是查找,查找效率代表了二叉排序中上各个操作的性能。对有n个结点的二叉排序树,若每个元素查找的概率相等,则二叉搜索树平均查找长度是结点在二叉搜索树的深度的函数,即结点越深,则比较次数越多


C(i)为查找到第i个数据元素时关键字的比较次数。


最好情况当二叉搜索树是完全二叉树时。

最坏情况当二叉搜索树是一支基本有序的单支二叉搜索树时。

因此最坏情况下,二叉排序树的平均查找长度为O(n),一般情况下平均查找长度为O(logn)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值