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;
}
}