数据结构习题——二叉树叶子结点的删除/删除以元素X为根的子树

前言

关于结点的删除例题,两道题目有类似的地方,一起记录下来。

正文

题目一:

二叉树叶子结点的删除
之前我认为的是,只要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),可以一起理解。

  • 4
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值