二叉排序树(二叉搜索树、二叉查找树):它或者是一棵空树,或者是具有以下性质的二叉树。
若它的左子树不空,则左子树上所有结点的值都小于它的根结点的值。
若它的右子树不空,则右子树上所有结点的值都大于它的根结点的值。
它的左右子树也分别为二叉排序树。
查找操作:
从根结点出发,用递归遍历二叉树,如果key<根结点T,则搜索其左子树,反之搜索其右子树,直到搜索成功,返回true,或者T为空,则返回false。
代码:
typedef struct BiNode
{
int data;
struct BiNode *lchild,*rchild;
}BiNode,*BiTree;
Status SearchBST(BiTree T, int key, BiTree f, BiTree *p) {
if(!T) {
*p=f;
return false;
}
else if(key==T->data) {
*p=T;
return true;
}
else if(key<T->data) {
return SearchBST(T->lchild, key, T, p);
}
else if(key>T->data) {
return SearchBST(T->rchild, key, T, p);
}
}
插入操作:
若二叉树中不存在关键字等于key的数据元素,则插入关键字等于key的元素,返回true,否则返回false。
代码:
Status InsertBST(BiTree *T, int key) {
BiTree p,s;
// 树中没有关键字等于key的数据元素(查找失败)
if(!SearchBST(*T, key, null, &p)) {
s=(Bitree)malloc(sizeof(BiNode));
s->data=key;
s->lchild=s->rchild=null;
if(!p) *T=s;
else if(key<p->data)
p->lchild=s;
else if(key>p->data)
p->rchild=s;
return true;
}
return false;
}
删除操作分三种情况:
1.若要删除的元素是叶子结点,则直接删除
2.若要删除的元素只有左子树或右子树,则删除之后,将其左子树或右子树移动到删除结点的位置(子承父业)。
3.若要删除的元素既有左子树又有右子树,则将与删除元素的值最接近的元素替换删除元素(该元素也是该树的中序遍历序列的直接前驱或直接后继),再删除该元素。
代码:
// 删除要删除的元素
Status DeleteBST(BiTree *T, int key) {
if(!*T) return false;
else {
if(key==(*T)->data)
return delete(T);
else if(key<(*T)->data)
return DeleteBST(&(*T)->lchild, key);
else if(key>(*T)->data)
return DeleteBST(&(*T)->rchild, key);
}
}
// 如果存在左右子树,则重接左右子树
Status Delete(BiTree *p) {
BiTree q,s;
if((*T)->rchild==null) {
q=*p;
*p=(*p)->lchild;
free(q);
}
else
if((*T)->lchild==null) {
q=*p;
*p=(*p)->rchild;
free(q);
}
else {
q=*p;
s=(*p)->lchild;
while(s->rchild) { // 找其直接前驱
q=s;
s=s->rchild;
}
(*p)->data=s->data;
if(q!=*p) // 若其左孩子有右子树
q->rchild=s->lchild;
else // 若其左孩子没有右子树
q->lchild=s->lchild;
free(s);
}
return true;
}