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);
}
由於在這裏我們認爲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;
}
}