上一篇(传送门:http://blog.youkuaiyun.com/xjtuse2014/article/details/51175592)关于二叉排序树的博客中,没有提到怎么删除一个节点,实际上,这也是BST(Binary Sort Tree)中稍微比较难一点的操作,但是,仔细分析的话,也很是很好理解的~~
先分析我们可能删除的结点属于哪种类型:
1. 叶子结点
2. 仅有左或右子树的结点
3. 左右子树都有结点
面对上面提到的1,2两种情况,直接删除就好了,注意释放空间;第三种情况时,就用递归方式对二叉排序树T查找key,查找到时就删除。
/*
* 若二叉排序树T中存在关键字等于key的数据元素时,删除该结点
* 并返回true,否则返回false
*/
bool DeleteBST(BiTree* T,int key){
if(!*T){
return false;//不存在关键字等于key的元素
}else{
if(key == T->data)//找到关键字等于key的数据元素
return Delete(T);
else if(key < T->data){
return DeleteBST(T->lchild,key);
else
return DeleteBST(T->rchild,key);
}
}
}
下面的代码则是Delete():
//从二叉排序树中删除结点,并重接它的左或右子树
//左右子树都空和判断出只有一边为空的效果是一样的~~,所以这里没有单独列出这种情况
bool Delete(BiTree* p){
BiTree q,s;
if(p->rchild == NULL){ //右子树空则只需重接它的左子树
q = *p;
*p = (*p).lchild;
free(q);
}else if(p->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; //s此时指向被删除结点的直接前驱
if(q!=p)
q -> rchild = s->lchild;//重接q的右子树
else
q->lchild = s->lchild;//重接q的左子树
free(s);
}
}
需要说明的是,对于第三种情况,我们的前驱来源是中序遍历了这个树,形成了一个顺序表,然后用待删除结点的前驱来代替它,因为这是他左边比他小但最接近它的一个数,当然,使用后继代替也是可以的。~~
对于这个不是很清楚的,先看看算法导论或者百度百科入个门:http://baike.baidu.com/link?url=70jU4KqcR5CY7iat43Cop4qaefwxtxXNxDnwzzUWANgIWiewnvQfRKT6XcPBEGQ4F_K-6E4JP_RtlF2RUVE0pK
欢迎交流~~