前言
为了记录下检索树删除算法,我来发个博客开心一下。
一 简要
1.1 基本原则
-
如何删除二叉树的元素?
- 通常删除以此元素为根的子树
-
如何删除检索树中的元素?
- 通常仅删除此元素且保中序有序
1.2 步骤
想要删除检索树中的结点,步骤:
- 找到要删除结点
- 找到要删除结点的父结点
- 找到要删除结点自己
- 找到删除
- 删除结点
- 该结点是叶子
- 该结点只有一个儿子:只有左儿子或者只有右儿子(同时要区分,该结点是它爹的哪个儿子,左儿子还是右儿子)
- 该结点有两个儿子:
- 该结点的左儿子没有右儿子:直接替代
- 该结点的左儿子有右儿子:先找到最右边的孙子,然后再替代。
二 代码
2.1 代码结构
https://naotu.baidu.com/file/2c072953bc2f3f1d768b4c90a2a00178
2.2 代码
int deleteT(element_type x, Bptr root)
{
Bptr f, p, q, s, r; //f: 要删除结点的父结点
p = NULL; // p将指向要删除的结点
f = root; // f的初值指向虚根(无穷小)
q = root->Rson; //q搜索指针
// 先找到
while (q) //循环查找x
{
if (x == q->data)
{
p = q;
q = NULL;
}
if (x < q->data) //向左搜索
{
f = q;
q = q->Lson;
}
else //向右搜索
{
f = q;
q = q->Rson;
}
}
if (!p) //未找到
return 0;
if (!p->Rson) //p没有右儿子,用左儿子代替p
{
if (p == f->Lson) //如果p是其父结点的左儿子
{
f->Lson = p->Lson;
delete p;
}
else //如果p是其父结点的右儿子
{
f-Rson = p->Lson;
delete p;
}
}
if (!p->Lson) //p没有左儿子,用右儿子代替p
{
if (p == f->Lson) //如果p是其父结点的左儿子
{
f->Lson = p->Rson;
delete p;
}
else //如果p是其父结点的右儿子
{
f-Rson = p->Rson;
delete p;
}
}
else //p有两个儿子,用中序前驱代替p
{
s = p->Lson; //s是p的左儿子
if (s->Rson == NULL) //左儿子s没有右儿子,用s代替p:左儿子带着它的儿子集体上位
{
p->data = s->data; //用s的值域代换p的值域
p->Lson = s->Lson; //删去s
delete s;
}
else //左儿子s有右儿子,查找p的左儿子的最右子孙r
{
r = s->Rson;
while (r->Rson) //找最右的子孙r
{
s = r;
r = r->Rson;
}
p->data = r->data; //用r的值域代换p的值域
s->Rson = r->Lson; //删去r
delete r;
}
}
return 1; //返回删除成功信息
} //函数结束