超详细的二叉搜索树讲解 附完整代码递归+非递归

二叉搜索树

概念

二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树

从图中可以直观看见,右子树节点值大于左子树节点值,且中序遍历是按一定顺序排列。

原理

二叉排序树的查找过程和次优二叉树类似,通常采取二叉链表作为二叉排序树存储结构中序遍历二叉排序树可得到一个关键字的有序序列,一个无序序列可以通过构造一棵二叉排序树变成一个有序序列,构造树的过程即为对无序序列进行排序的过程。每次插入的新的结点都是二叉排序树上新的叶子结点,在进行插入操作时,不必移动其它结点,只需改动某个结点的指针,由空变为非空即可。搜索,插入,删除的复杂度等于树高,O(log(n)).

操作
template<class T>//定义结点的结构体
struct Node
{
	typedef struct Node* _pNode;
	_pNode _pRight;
	_pNode _pLeft;
	T _data;
public:
	Node(T data)
		:_pRight(NULL)
		,_pLeft(NULL)
	{
		_data = data;
	}
	Node()
		:_pRight(NULL)
		,_pLeft(NULL)
	{
		_data = T();
	}

};

1.插入

先判断插入节点值大于根节点,若大于插入右子树,小于插入左子树。

//非递归
	bool _Insert(const T data)
	{
		_pNode pCur = _Root;
		_pNode pParent = NULL;
		if(_Root != NULL)
		{
			while(pCur)
			{
				pParent = pCur;
				if(pCur->_data > data)
				{
					pCur = pCur->_pLeft;
				}
				else if(pCur->_data < data)
				{
					pCur = pCur->_pRight;
				}
				else
				{
					return false;
				}
			}
			if(pParent != NULL)
			{
				if(pParent->_data < data)
				{
					pParent->_pRight = new _Node(data);
				}
				else
				{
					pParent->_pLeft = new _Node(data);
				}
				return true;
			}
			return false;
		}
		else
		{
			_Root =  new _Node(data);
			return true;
		}
	}
//递归
	bool Insert(const T data)
	{
		return _recInsert(_Root, data);
	}
        bool _recInsert(_pNode& pCur, const T data)
	{
		if(pCur == NULL)
		{
			pCur = new _Node(data);
			return true;
		}

		if(pCur->_data > data)
		{
			return _recInsert(pCur->_pLeft, data);
		}
		else if(pCur->_data < data)
		{
			return _recInsert(pCur->_pRight, data);
		}
		else
		{
			return false;
		}
	}

2.查找

原理:类似于插入

	//非递归
	_pNode _find(const T& data)
	{
		_pNode pCur = _Root;
		while(pCur)
		{
			if(pCur->_data == data)
				return pCur;
			else if(pCur->_data > data)
			{

				pCur = pCur->_pLeft;
			}
			else
			{
				pCur = pCur->_pRight;
			}
		}
		return NULL;
	}
//递归
_pNode Find(const T data)
	{
		return _recFind(_Root, data);
	}
_pNode _recFind(_pNode& pCur, const T data)
	{
		if(pCur->_data == data)
		{
			return pCur;
		}

		if(pCur->_data > data)
		{
			return _recFind(pCur->_pLeft, data);
		}
		else if(pCur->_data < data)
		{
			return _recFind(pCur->_pRight, data);
		}
		else
		{
			return NULL;
		}
	}

3.删除

删除分为三种情况:

1.删除仅有左子树节点;

2.删除仅有右子树节点;

3.删除既有左子树又有右子树节点;

其中叶子节点的情况可包含在1或者2情况中;

**********************************************************************************

1.删除仅有左子树节点:

当删除C节点时,可以直接将指向C的节点直接指向C的左子树;

2.删除仅有右子树节点:


当删除I节点时,可以直接将指向I的节点直接指向I的右子树;

3.删除既有左子树又有右子树节点:


a.删除左子树上的结点(例如D)

保存D的左子树,指向D的结点指向D的右子树,在让现在D的左子树的叶子节点指向之前保存D的左子树。

b.删除右子树上的结点(例如H)

保存H的右子树,指向H的结点指向H的右子树,在让现在H的左子树的叶子节点指向之前保存H的左子树。

c.删除根结点(例如F)

保存F的左子树,根节点变成根节点的右子树,在让现在F的左子树的叶子节点指向之前保存F的左子树。

 //非递归
	bool _delete(const T& data)
	{
		_pNode pCur = _Root;
		_pNode pParent = NULL;
		while(pCur)
		{
			if(pCur->_data < data)
			{
				pParent = pCur;
				pCur = pCur->_pRight;
			}
			else if(pCur->_data > data)
			{
				pParent = pCur;
				pCur = pCur->_pLeft;
			}
			else
			{
				break;
			}
		}
		if(pCur == NULL)
		{
			return false;
		}
		if(pCur->_pRight == NULL)
		{
			pParent->_pLeft = pCur->_pLeft;
			delete pCur;
		}
		else if(pCur->_pLeft == NULL)
		{
			pParent->_pRight = pCur->_pRight;
			delete pCur;
		}
		else
		{
			if(pParent != NULL)
			{
				if(pParent->_pLeft->_data == data)
				{
					pParent->_pLeft = pCur->_pRight;
				}
				else
				{
					pParent->_pRight = pCur->_pRight;
				}
				_pNode tempLeft = pCur->_pLeft;
				_pNode newdel = pCur->_pRight;
				while(newdel->_pLeft != NULL)
				{
					newdel =  newdel->_pLeft;
				}
				newdel->_pLeft = tempLeft;
				delete pCur;
			}
			else
			{
				_pNode tempLeft = pCur->_pLeft;
				_Root = _Root->_pRight;
				_pNode tempRight = _Root;
				while(tempRight->_pLeft != NULL)
				{
					tempRight =  tempRight->_pLeft;
				}
				tempRight->_pLeft = tempLeft;
				delete pCur;
			}
		}

	}
//递归
bool Delete(const T data)
	{
		return _recDelete(_Root, data);
	}
bool _recDelete(_pNode& pCur, const T data)
	{
		if(pCur->_data == data)
		{
			if(NULL == pCur->_pRight)
			{
				_pNode del = pCur;
				pCur = pCur->_pLeft;
				delete pCur;
				return true;
			}
			else if(NULL == pCur->_pLeft)
			{
				_pNode del = pCur;
				pCur = pCur->_pRight;
				delete pCur;
				return true;
			}
			else
			{
				_pNode del = pCur->_pRight;
				while(del->_pLeft)
				{
					del = del->_pLeft;
				}
				pCur->_data = del->_data;
				return _recDelete(pCur->_pRight, del->_data);
			}
		}

		if(pCur->_data > data)
		{
			return _recDelete(pCur->_pLeft, data);
		}
		else if(pCur->_data < data)
		{
			return _recDelete(pCur->_pRight, data);
		}
		else
		{
			return false;
		}
	}

完整代码:

#include <iostream>
using namespace std;

template<class T>
struct Node
{
	typedef struct Node* _pNode;
	_pNode _pRight;
	_pNode _pLeft;
	T _data;
public:
	Node(T data)
		:_pRight(NULL)
		,_pLeft(NULL)
	{
		_data = data;
	}
	Node()
		:_pRight(NULL)
		,_pLeft(NULL)
	{
		_data = T();
	}

};

template<class T>
class BSTree
{
	typedef struct Node<T> _Node;
	typedef struct Node<T>*  _pNode;
public:
	BSTree()
	{
		_Root = NULL;
	}


	void _Inorder()
	{
		Inorder(_Root);
	}

	
	//非递归
	bool _Insert(const T data)
	{
		_pNode pCur = _Root;
		_pNode pParent = NULL;
		if(_Root != NULL)
		{
			while(pCur)
			{
				pParent = pCur;
				if(pCur->_data > data)
				{
					pCur = pCur->_pLeft;
				}
				else if(pCur->_data < data)
				{
					pCur = pCur->_pRight;
				}
				else
				{
					return false;
				}
			}
			if(pParent != NULL)
			{
				if(pParent->_data < data)
				{
					pParent->_pRight = new _Node(data);
				}
				else
				{
					pParent->_pLeft = new _Node(data);
				}
				return true;
			}
			return false;
		}
		else
		{
			_Root =  new _Node(data);
			return true;
		}
	}

	//非递归
	_pNode _find(const T& data)
	{
		_pNode pCur = _Root;
		while(pCur)
		{
			if(pCur->_data == data)
				return pCur;
			else if(pCur->_data > data)
			{

				pCur = pCur->_pLeft;
			}
			else
			{
				pCur = pCur->_pRight;
			}
		}
		return NULL;
	}
    //非递归
	bool _delete(const T& data)
	{
		_pNode pCur = _Root;
		_pNode pParent = NULL;
		while(pCur)
		{
			if(pCur->_data < data)
			{
				pParent = pCur;
				pCur = pCur->_pRight;
			}
			else if(pCur->_data > data)
			{
				pParent = pCur;
				pCur = pCur->_pLeft;
			}
			else
			{
				break;
			}
		}
		if(pCur == NULL)
		{
			return false;
		}
		if(pCur->_pRight == NULL)
		{
			pParent->_pLeft = pCur->_pLeft;
			delete pCur;
		}
		else if(pCur->_pLeft == NULL)
		{
			pParent->_pRight = pCur->_pRight;
			delete pCur;
		}
		else
		{
			if(pParent != NULL)
			{
				if(pParent->_pLeft->_data == data)
				{
					pParent->_pLeft = pCur->_pRight;
				}
				else
				{
					pParent->_pRight = pCur->_pRight;
				}
				_pNode tempLeft = pCur->_pLeft;
				_pNode newdel = pCur->_pRight;
				while(newdel->_pLeft != NULL)
				{
					newdel =  newdel->_pLeft;
				}
				newdel->_pLeft = tempLeft;
				delete pCur;
			}
			else
			{
				_pNode tempLeft = pCur->_pLeft;
				_Root = _Root->_pRight;
				_pNode tempRight = _Root;
				while(tempRight->_pLeft != NULL)
				{
					tempRight =  tempRight->_pLeft;
				}
				tempRight->_pLeft = tempLeft;
				delete pCur;
			}
		}

	}

//递归
	bool Insert(const T data)
	{
		return _recInsert(_Root, data);
	}
	_pNode Find(const T data)
	{
		return _recFind(_Root, data);
	}
	bool Delete(const T data)
	{
		return _recDelete(_Root, data);
	}

private:
	bool _recDelete(_pNode& pCur, const T data)
	{
		if(pCur->_data == data)
		{
			if(NULL == pCur->_pRight)
			{
				_pNode del = pCur;
				pCur = pCur->_pLeft;
				delete pCur;
				return true;
			}
			else if(NULL == pCur->_pLeft)
			{
				_pNode del = pCur;
				pCur = pCur->_pRight;
				delete pCur;
				return true;
			}
			else
			{
				_pNode del = pCur->_pRight;
				while(del->_pLeft)
				{
					del = del->_pLeft;
				}
				pCur->_data = del->_data;
				return _recDelete(pCur->_pRight, del->_data);
			}
		}

		if(pCur->_data > data)
		{
			return _recDelete(pCur->_pLeft, data);
		}
		else if(pCur->_data < data)
		{
			return _recDelete(pCur->_pRight, data);
		}
		else
		{
			return false;
		}
	}
	_pNode _recFind(_pNode& pCur, const T data)
	{
		if(pCur->_data == data)
		{
			return pCur;
		}

		if(pCur->_data > data)
		{
			return _recFind(pCur->_pLeft, data);
		}
		else if(pCur->_data < data)
		{
			return _recFind(pCur->_pRight, data);
		}
		else
		{
			return NULL;
		}
	}
	bool _recInsert(_pNode& pCur, const T data)
	{
		if(pCur == NULL)
		{
			pCur = new _Node(data);
			return true;
		}

		if(pCur->_data > data)
		{
			return _recInsert(pCur->_pLeft, data);
		}
		else if(pCur->_data < data)
		{
			return _recInsert(pCur->_pRight, data);
		}
		else
		{
			return false;
		}
	}


private:
	void Inorder(_pNode pCur)
	{
		if(!pCur)
			return;
		Inorder(pCur->_pLeft);
		cout<<pCur->_data<<" ";
		Inorder(pCur->_pRight);
	}


private:
	_pNode _Root;
};


void TestFun()
{
	BSTree<int> tree;
	tree.Insert(5);
	tree.Insert(3);
	tree.Insert(4);
	tree.Insert(2);
	tree.Insert(1);
	tree.Insert(7);
	tree.Insert(6);
	tree.Insert(8);
	tree.Insert(9);
	tree._Inorder();
	cout<<endl;
	tree.Delete(3);
	tree._Inorder();
	cout<<endl;




}




int main()
{
	TestFun();
	return 0;
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

BugGuys

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

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

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

打赏作者

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

抵扣说明:

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

余额充值