二叉搜索樹的實現(查找,插入,刪除的遞歸與非遞歸)

BST定義:

二叉搜索樹:又稱二叉排序樹,它或者是一棵空樹,或者是具有以下性質的二叉樹
1、若它的左子樹不爲空,則左子樹上所有節點的值都小於根節點的值
2、若它的右子樹不爲空,則右子樹上所有節點的值都大於根節點的值
3、它的左右子樹也分別爲二叉搜索樹

除此之外,還有一點值得在意:二叉搜索樹的最左節點是所有節點的值中最小值,而最右節點則是最大值。

BST的實現:

1.節點的定義:

template<class K,class V>
struct Node
{
	Node(const K& key,const V& value)
		:_key(key)
		,_value(value)
		,_pLeft(NULL)
		,_pRight(NULL)
	{}


	K _key;
	V _value;
	Node<K,V>* _pLeft;
	Node<K,V>* _pRight;
};
2.查找節點中指定key值的節點的實現

①非遞歸

Node* Find(const K& key)    //外部接口
{
	return _Find(_pRoot,key);
}

Node* _Find(Node* pRoot,const K& key)  //實現方法
{
	if(pRoot==NULL)
		return NULL;

	while(pRoot)
	{
		if(key<pRoot->_key)
		{
			pRoot=pRoot->_pLeft;
		}
		else if(key>pRoot->_key)
		{
			pRoot=pRoot->_pRight;
		}
		else
			return pRoot;
	}

	return NULL;
}

②非遞歸

Node* Find(const K& key)   //外部接口
{
	return _Find(_pRoot,key);
}

Node* _Find(Node* pRoot,const K& key)   //實現方法
{
	if(pRoot==NULL)
		return NULL;

	if(pRoot->_key==key)
		return pRoot;
	else if(key<pRoot->_key)
		return _Find(pRoot->_pLeft,key);
	else
		return _Find(pRoot->_pRight,key);
}


3.插入指定key值與value值的節點

由於在這裏我們認爲key值是區分這些節點的關鍵字,而且是不能重複的,所以有以下實現:

①非遞歸

bool Insert(const K& key, const V& value)   //外部接口
{
	return _Insert(_pRoot,key,value);
}

bool _Insert(Node*& pRoot,const K& key,const V& value)    //實現方法
{
	if(pRoot==NULL)
	{
		pRoot=new Node(key,value);
		return true;
	}

	Node* pcur=pRoot;
	Node* parent=NULL;
	while(pcur)
	{
		if(pcur->_key==key)
			return false;
		else if(key<pcur->_key)
		{
			parent=pcur;
			pcur=pcur->_pLeft;
		}
		else
		{
			parent=pcur;
			pcur=pcur->_pRight;
		}
	}

	pcur=new Node(key,value);
	if(key<parent->_key)
		parent->_pLeft=pcur;
	else
		parent->_pRight=pcur;

	return true;
}

②遞歸

bool Insert(const K& key, const V& value)   //外部接口
{
	return _Insert(_pRoot,key,value);
}

bool _Insert(Node*& pRoot,const K& key,const V& value)   //實現方法
{
	if(pRoot==NULL)
	{
		pRoot=new Node(key,value);
		return true;
	}

	if(pRoot->_key==key)
		return false;
	
	if(key<pRoot->_key)
		return _Insert(pRoot->_pLeft,key,value);
	else
		return _Insert(pRoot->_pRight,key,value);
}


4.刪除指定key值的節點

對於刪除這一操作,我們仔細分析一下當中節點可能的情況:

1.有右孩子無左孩子,且在雙親的右子樹中


2.有右孩子無左孩子,且在雙親的左子樹中


3.有右孩子無左孩子,且爲根節點


4.有左孩子無右孩子,且在雙親的右子樹中


5.有左孩子無右孩子,且在雙親的左子樹中


6.有左孩子無右孩子,且爲根節點


7.有左孩子有右孩子,且爲根節點


8.有左孩子有右孩子,但不爲根節點


①非遞歸

bool Remove(const K& key)    //外部接口
{
	return _Remove(_pRoot,key);
}


bool _Remove(Node*& pRoot,const K& key)     //實現方法
{
	if(pRoot==NULL)
		return false;

	Node* pcur=pRoot;
	Node* parent=NULL;
	while(pcur)
	{
		if(key<pcur->_key)
		{
			parent=pcur;
			pcur=pcur->_pLeft;
		}
		else if(key>pcur->_key)
		{
			parent=pcur;
			pcur=pcur->_pRight;
		}
		else
		{
			if(pcur->_pLeft==NULL)
			{
				if(pcur==pRoot)
					pRoot=pcur->_pRight;

				else if(pcur==parent->_pLeft)
					parent->_pLeft=pcur->_pRight;
				else
					parent->_pRight=pcur->_pRight;
			}
			else if(pcur->_pRight==NULL)
			{
				if(pcur==pRoot)
					pRoot=pcur->_pLeft;

				else if(pcur==parent->_pLeft)
					parent->_pLeft=pcur->_pLeft;
				else
					parent->_pRight=pcur->_pLeft;
			}
			else
			{
				Node* pDel=pcur;
				parent=pcur;
				pDel=pDel->_pRight;
				while(pDel->_pLeft)
				{
					parent=pDel;
					pDel=pDel->_pLeft;
				}
				pcur->_key=pDel->_key;
				pcur->_value=pDel->_value;

				if(pDel==parent->_pLeft)
				{
					parent->_pLeft=pDel->_pRight;
				}
				else
				{
					parent->_pLeft=pDel->_pRight;
				}

				pcur=pDel;
			}

			delete pcur;
			return true;
		}
	}

	return false;
}


②遞歸

bool Remove(const K& key)   //外部接口
{
	return _Remove(_pRoot,key);
}


bool _Remove(Node*& pRoot,const K& key)    //實現方法
{
	if(pRoot==NULL)
		return false;
	
	if(key<pRoot->_key)
		return _Remove(pRoot->_pLeft,key);
	else if(key>pRoot->_key)
		return _Remove(pRoot->_pRight,key);
	else
	{
		Node* pcur=pRoot;
		if(pcur->_pLeft==NULL)
		{
			pRoot=pcur->_pRight;
			delete pcur;
		}
		else if(pcur->_pRight==NULL)
		{
			pRoot=pcur->_pLeft;
			delete pcur;
		}
		else
		{
			Node* pDel=pRoot;
			pcur=pcur->_pRight;
			while(pcur->_pLeft)
			{
				pcur=pcur->_pLeft;
			}
			pDel->_key=pcur->_key;
			pDel->_value=pcur->_value;
			_Remove(pRoot->_pRight,pcur->_key);

		}
		return true;
	}
}







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章