二叉排序树(二叉搜索树)
知识点总结报告
知识点:
二叉排序树
(原理)二叉排序树又称二叉搜索树。其定义为二叉排序树或者空树或者满足以下性质的二叉树。
性质1
若根节点的左子树非空,则左子树上的所有结点关键字均小于根结点关键字
性质2
若根节点的右子树非空,则右子树上的所有结点关键字均大于根结点关键字
性质3
根结点的左、右子树本身又各是一棵二叉排序树
二叉排序树结点类型
typede fstruct node //元素类型
{ KeyType key; //关键字项
Info Type data; //其他数据域
struct node *lchild,*rchild; //左、右孩子指针
}BSTNode;
二叉排序树的插入和创建
插入的递归算法InsertBST( )
bool InsertBST(BSTNode *&bt,KeyType k) //在二叉排序树bt中插入一个关键字为k的结点,若插入成功返回真,否则返回假
{ if (bt==NULL) //原树为空,新插入的结点为根结点
{ bt=(BSTNode *)malloc(sizeof(BSTNode));
bt->key=k;bt->lchild=bt->rchild=NULL;
return true;
}
else if(k==bt->key) //树中存在相同关键字的结点,返回假
return false;
else if(k<bt->key)
return InsertBST(bt->lchild,k); //插入到左子树中
else
return InsertBST(bt->rchild,k); //插入到右子树中
}
创建二叉排序树CreateBST( )
BSTNode *CreateBST(KeyType A[ ],int n) //创建二叉排序树 返回BST树根结点指针
{ BSTNode *bt=NULL; //初始时bt为空树
int i=0;
while(i<n)
{ InsertBST(bt,a[i]); //将关键字a[i]插入二叉排序树bt中
i++;
}
return bt; //返回建立的二叉排序树的根指针
}
二叉排序树的查找(在二叉排序树bt上查找关键字为k的元素,成功时返回该结点指针,否则返回NULL)
BSTNode *SearchBST(BSTNode *bt,KeyType k) //二叉排序树查找
{ if(bt==NULL||bt->key==k) //递归结束条件
return bt;
if(k<bt->key)
return SearchBST(bt->lchild,k); //在左子树中递归查找
else
return SearchBST(bt->rchild,k); //在右子树中递归查找
}
如果不仅要找到关键字为k的结点,还要找到双亲结点,采用递归算法如下:
BSTNode *SearchBST1(BSTNode *bt,KeyType k,BSTNode *f1,BSTNode *&f)/*在二叉排序树bt上查找关键字为k的结点,若查找成功,该函数返回该结点指针,f返回其双亲结点,否则,该函数返回NULL,调用方法如下SearchBST1(bt,x,NULL,f); 这里的第3个参数f1仅作中间参数,用于求f,初始设为NULL*/
{ if(bt==NULL)
{ f=NULL;
return (NULL);
}
else if(k==bt->key)
{ f=f1;
return(bt);
}
else if(k<bt->key)
return SearchBST1(bt->lchild,k,bt,f); //在左子树中递归查找
else
return SearchBST1(bt->rchild,k,bt,f); //在右子树中递归查找
}
二叉排序树的删除
删除过程分为以下几种情况:(删除操作必须首先进行查找,设在查找结束时p指向要删除的结点)
(1)若p结点是叶子结点,直接删去该结点。这是最简单的删除结点情况。
(2)若p结点只有左子树没有右子树。根据二叉排序树的特点,可以直接将其左孩子替代结点p(结点替换)。
(3)若p结点只有右子树没有左子树。根据二叉排序树的特点,可以直接将其右孩子替代结点p(结点替换)。
(4)若p结点同时存在左、右子树。根据二叉排序树的特点,可以从左子树中选择关键字最大的结点r,用结点r的值替代结点p的值(结点值替换),并删除结点r(由于r结点一定没有右孩子,删除它属于情况(2)),原理是用中序前驱替代被删结点。
也可以从其右子树中选择关键字最小的结点r,用结点r的值替代结点p的值(结点值替换),而且将它删除(由于r结点一定没有左子树,删除它属于情况(3))。原理是用中序后继结点替代被删结点。
首先查找关键字为k的被删结点p.
bool deletek(BSTNode *&bt,KeyType k)
{ if (bt!=NULL)
{ if(k==bt->key)} //查找到了被删结点bt
{ deletep(bt); //调用deletep删除结点bt
return true; //成功删除,返回真
}
else if(k<bt->key)
deletek(bt->lchild,k); //在左子树中查找
else
deletek(bt->rchild,k); //在右子树中查找
}
else return false; //未查找到,返回假
}
删除结点p(结点p仅有右子树)
void deletep(BSTNode *&p)
{ BSTNode *q;
q=p; //让q指向结点p
p=p->rchild; //让p指向它的右孩子
free(q); //释放结点q的空间
}
删除二叉排序树bt中关键字为k的结点
bool DeleteBST(BSTNode *&bt,KeyType k) //在bt中删除关键字为k的结点
{ if(bt==NULL)
return false; //空树删除失败,返回假
else
{ if(k<bt->key)
return DeleteBST(bt->lchild,k); //递归在左子树中删除为k的结点
else if (k>bt->key)
return DeleteBST(bt->rchild,k); //递归在右子树中删除为k的结点
else //找到了要删除的结点bt
{ Delete(bt); //调用Delete(bt)函数删除结点bt
return true; //删除成功,返回真
}
}
}
void Delete(BSTNode *&p) //从二叉排序树中删除结点p
{ BSTNode *q;
if(p->rchild==NULL) //结点p没有右子树(含为叶子结点)的情况
{ q=p;
p=p->lchild; //用结点p的左孩子替代它
free(q);
}
else if(p->lchild==NULL) //结点p没有左子树的情况
{ q=p;
p=p->rchild; //用结点p的右孩子替代它
free(q);
}
else Delete1(p,p->lchild); //结点p既没有左子树又没有右子树的情况
}
void Delete1(BSTNode *p,BSTNode *&r) //被删结点p有左、右子树,r指向其左孩子
{ BSTNode *q;
if(r->rchild!=NULL) //递归找结点r的最右下结点
Delete1(p,r->rchild);
else //找到了最右下结点r(它没有右子树)
{ p->key=r->key; //将结点r的值存放到结点p中(结点值替代)
p->data=r->data;
q=r; //删除结点r
r=r->lchild; //即用结点r的值存放到结点p中(结点值替代)
free(q); //释放结点q的空间
}
}