前言
关于结点的删除例题,两道题目有类似的地方,一起记录下来。
正文
题目一:
二叉树叶子结点的删除
之前我认为的是,只要free()掉叶子结点就可以了,但是为了避免野指针的出现,我们还需要将指向叶子结点的双亲的左右指针置为NULL!
代码
void Del_0(BiTree T) //删除叶子结点
{
BiTNode *p = T;
if ((p->lchild == NULL && p->rchild == NULL) || p == NULL)
{
free(p);
return;
}
else if (p->lchild->lchild == NULL && p->lchild->rchlid == NULL)
{
free(p->lchild);
p->lchild = NULL; //父节点左孩子指针置空
}
else if (p->rchild->lchild == NULL && p->rchild->rchlid == NULL)
{
free(p->rchild);
p->rchild = NULL; //父节点右孩子指针置空
}
Del_0(T->lchild);
Del_0(T->rchild);
//注意此代码为递归,只会向内层深入
//所以删除完叶子结点,使原分支结点变为叶子结点,但不会再继续删除
}
代码源自:https://blog.csdn.net/qq_36645322/article/details/102711907
下面是另一种写法,原笔者有误,我改了一下,若不对请斧正。
代码
//删除叶子节点
void Delete_leaf(BTNode *t){
if(t==NULL) return;//t是空子树
if(t->lchid==NULL&&t->rchild==NULL){//根结点为叶子结点
free(t);
return;
}
/*找到叶子结点的父双亲结点,删除后使双亲结点置空*/
if(t->lchild!=NULL){
BTNode* tlchild=t->lchild;
if(tlchild->lchild==NULL&& tlchild->rchild==NULL){
free(tlchild);//free叶子结点
t->lchild=NULL;//使双亲结点指向叶子结点的那个指针赋值为NULL
}
}
if(t->rchild!=NULL){
BTNode *trchild=t->rchild;
if(trchild->lchild==NULL&& trchild->rchild==NULL){
free(trchild);
t->rchild=NULL;
}
}
Delete_leaf(t->lchild);
Delete_leaf(t->rchild);
}
代码源自:https://www.cnblogs.com/zzuuoo666/p/12083189.html
题目二:
删除以元素X为根的子树
先要先一个个删除x的子树最后再删除X,所以要用后续遍历来删除。
删除x及其子树后,为了避免其双亲结点成为野指针,要让其指向NULL。所以用层序遍历来找到X的父结点。
代码
#include <stdio.h>
//删除以x元素为根的所有子树
void Del_x(Bitree bt) //后序遍历删除以bt为根的子树
{
if(bt)
{
Del_x(bt->lchild);
Del_x(bt->rchlid);
free(bt);
}
}
//在二叉树上查找所有以x为元素值的结点,并删除以其为根的子树
void Search_x(Bitree bt,Elempty x)
{
Bitree Q[]; //Q是存放二叉树结点指针的队列。容量足够大
if(bt) //在树非空的情况下进行
{
if(bt->data==x) //若根结点的值为x,则删除整棵树
{
Del_x(bt);
exit(0);
}
InitQueue(Q);
EnQueue(Q,bt);
while(!IsEmpty(Q))
{
DeQueue(Q,p); //删除队头元素,并用p返回
if(p->lchild) //如果右子树不空
{
if(p->lchild->data==x) //左子树符合删除左子树
{
Del_x(p->lchild);
p->lchild==NULL;//父节点的左子女置空
}
else
EnQueue(Q,p->lchild);
}
if(p->rchild) //如果右子树不空
{
if(p->rchild->data==x)
{
Del_x(p->rchild);
p->rchild=NULL;
}
else
EnQueue(Q,p->rchlid);
}
}
}
}
这个代码和上面的删除叶子结点的第二种代码相似,都是找到符合条件结点的双亲结点,删除后使双亲结点置空(指向NULL),可以一起理解。