二叉搜索树
【概念】
二叉搜索树:又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树
1、若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
2、若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
3、它的左右子树也分别为二叉搜索树
例:此树就是一颗二叉搜索树。
【操作】
—搜索:若根节点不为空
如果根节点的key==查找key,返回true
如果根节点的key<查找key,在其左子树中查找
如果根节点的key>查找key,在其右子树中查找
否则,返回false
—插入:
在向二叉搜索树中插入新元素时,必须先检测这个元素是否在树中已经存在。如果搜索成功,说明该元素已经存在,则不进行插入;否则将新元素加入到搜索停止的地方。
—删除:
首先查找元素是否在二叉搜索树中,如果不存在,则返回;否则要删除的结点可能分下面四种情况:
1、要删除的结点无孩子结点;
2、要删除的结点只有左孩子结点;
3、要删除的结点只有右孩子结点;
4、要删除的结点有左、右孩子结点;
对于上述情况,相应的删除方法如下:
a、直接删除该结点
b、删除该结点且使被删除节点的双亲结点指向被删除节点的左孩子点;
c、删除该结点且使被删除节点的双亲结点指向被删除结点的右孩子点;
d、在它的右子树中寻找中序下的第一个结点(关键码最小),用它的值补 到被删除节点中,在来处理该结点的删除问题
1–>a :
2–b :
3–c :
4–d :
源代码:
template<class T>
struct BinarySearchTreeNode
{
BinarySearchTreeNode<T>*_pleft;
BinarySearchTreeNode<T>*_pright;
T _key;
BinarySearchTreeNode(const T&key)
:_pleft(NULL)
, _pright(NULL)
, _key(key)
{}
};
template<class T>
class BinarySearchTree
{
typedef BinarySearchTreeNode<T> Node;
public:
BinarySearchTree()
:_proot(NULL)
{}
BinarySearchTree(T*a, size_t size)
{
_proot = NULL;
for (int i = 0; i < size; ++i)
{
Insert(a[i]);
}
}
bool Insert(const T&data)
{
if (_proot == NULL)
{
_proot = new Node(data);
return true;
}
Node*pCur = _proot;
Node*parent = NULL;
while (pCur)
{
parent = pCur;
if (pCur->_key < data)
pCur = pCur->_pright;
else if (pCur->_key>data)
pCur = pCur->_pleft;
else
return false;
}
if (parent->_key < data)
parent->_pright = new Node(data);
else if(parent->_key > data)
parent->_pleft = new Node(data);
return true;
}
Node* Find(const T&data)
{
Node*pCur = _proot;
while (pCur)
{
if (data == pCur->_key)
return pCur;
if (data < pCur->_key)
pCur = pCur->_pleft;
else
pCur = pCur->_pright;
}
return NULL;
}
bool Remove(const T&data)
{
Node*pCur = _proot;
Node*parent = NULL;
while (pCur)
{
if (pCur->_key < data)
{
parent = pCur;
pCur = pCur->_pright;
}
else if (pCur->_key>data)
{
parent = pCur;
pCur = pCur->_pleft;
}
else
{
if (pCur->_pleft == NULL)//当前节点左孩子为空,将右孩子直接复制
{
if (parent == NULL)//判断当前节点是不是根节点
{
_proot = pCur->_pright;
}
else//待删除结点为右孩子
{
if (parent->_pleft == pCur)
parent->_pleft = pCur->_pright;
else
parent->_pright = pCur->_pright;
}
delete pCur;
}
else if (parent->_pright == NULL)//待删除结点为左孩子
{
if (parent == NULL)
{
_proot = pCur->_pright;
}
else
{
if (parent->_pleft == pCur)
parent->_pleft = pCur->_pleft;
else
parent->_pright = pCur->_pleft;
}
delete pCur;
}
else//左右子树都不为空,将右子树中最左节点交换
{
Node*tmp = pCur->_pright;
Node*prev = pCur;
while (tmp->_pleft)
{
prev = tmp;
tmp = tmp->_pleft;
}
swap(tmp->_key, pCur->_key);
if (tmp==prev->_pright)
{
pCur->_pright = tmp->_pright;
}
else if (prev->_pleft==tmp)
{
prev->_pleft = tmp->_pright;
}
delete tmp;
}
return true;
}
}
return false;
}
BinarySearchTree<T>& operator=(BinarySearchTree<T>&tree)
{
if (this != &tree)
{
BinarySearchTree<T>tmp(tree);
swap(_proot, tmp._proot);
}
return *this;
}
BinarySearchTree(const BinarySearchTree<T>&tree)
:_proot(NULL)
{
if (tree._proot == NULL)
return;
queue<Node*>q;
q.push(tree._proot);
while (!q.empty())
{
Node*pCur = q.front();
Insert(pCur->_key);
q.pop();
if (pCur->_pleft)
{
q.push(pCur->_pleft);
}
if (pCur->_pright)
{
q.push(pCur->_pright);
}
}
}
~BinarySearchTree()
{
_Destory(_proot);
}
Node*_Find_Min(const Node&proot)
{
assert(proot);
while (proot->_pleft)
{
proot = proot->_pleft;
}
return proot;
}
Node*_Find_MAX(const Node&proot)
{
assert(proot);
while (proot->_pright)
{
proot = proot->_pright;
}
return proot;
}
private:
void _Destory(Node*proot)
{
if (proot == NULL)
return;
_Destory(proot->_pleft);
_Destory(proot->_pright);
delete proot;
}
private:
BinarySearchTreeNode<T>*_proot;
};