二叉排序树又称二叉查找树,它或是一棵空的二叉树,或是具有下列性质的二叉树:
- 若它的左子树不空,则左子树上所有节点的值均小于根节点的值
- 若它的右子树不空,则右子树上所有节点的值均大于根节点的值
- 它的左右子树也都是二叉排序树
由上述定义可知,
中虚遍历二叉排序树可以得到一个按关键码有序的序列。
template<class T>
struct BiNode
{
T data;
BiNode<T>*lchild,rchild;
}
class BiSortTree
{
public:
BiSortTree(int a[],int n);
~BiSortTree();
void InsertBST(BiNode<int>*root,BiNode<int>*s);
void DeleteBST(BiNode<int>*p,BiNode<int>*f);
BiNode<int>*SearchBST(BiNode<int>*root,int k);
private:
BiNode<int>*root;
}
void BiSortTree::InsertBST(BiNode<int>*root,BiNode<int>*s)
{
if(root==NULL)
root=s;
else if(s->data<root->data)
InsertBST(root->lchild,s);
else
InsertBST(root->rchild,s);
}
BiSortTree::BiSortTree(int r[],int n)
{
for(int i=0;i<n;i++)
{
BiNode<int>s=new BiNode<int>;
s->data=r[i];
s->lchild=s->rchild=NULL;
InsertBST(root,s);
}
}
//在二叉排序树中删除一个节点f的左孩子节点p的算法:
//1.若节点p是叶子,则直接删除节点p
//2.若节点p只有左子树,则需重接p的左子树;若节点p只有右子树,则需重接p的右子树
//3.若节点p的左右子树都不为空,则
// 3.1查找节点p的右子树上的最左下节点s以及节点s的双亲节点par
// 3.2将节点s的数据域替换到被删除节点p的数据域
// 3.3若节点p的右孩子无左子树,则将s的右子树接到par的右子树上;否则将s的右子树接到节点par的左子树上
// 3.4删除节点s;
void BiSortTree::DeleteBST(BiNode<int>*p,BiNode<int>*f)
{
if((p->lchild==NULL)&&(p->rchild)==NULL)
{
f->lchild=NULL;
delete p;
}
else if(p->rchild==NULL)
{
f->lchild=p->lchild;
delete p;
}
else if(p->lchild==NULL)
{
f->lchild=p->rchild;
delete p;
}
else{
BiNode<int>*par=p;
BiNode<int>*s=p->rchild;
while(s->lchild!=NULL)
{
par=s;
s=s->lchild
}
p->data=s->data;
if(par==p)
par->rchild=s->rchild;
else
par->lchild=s->rchild;
delete s;
}
}
BiNode<int>*BiSortTree::SearchBST(BiNode<int>*root,int k)
{
if(root==NULL)
return NULL;
else if(root->data==k)
return root;
else if(root->date>k)
return SearchBST(root->lchild,k);
else if(root->data<k)
return SearchBST(root->rchild,k);
}
给定值的比较次数等于给定值节点在二叉排序树中的层数。如果二叉排序树是平衡的,则n个节点的二叉排序树的高度为Log 2n+1,其查找效率为O(Log 2n),近似于折半查找。如果二叉排序树完全不平衡,则其深度可达到n,查找效率为O(n),退化为顺序查找。一般的,二叉排序树的查找性能在O(Log 2n)到O(n)之间。因此,为了获得较好的查找性能,就要构造一棵平衡的二叉排序树。