树(Tree)——(五)搜索二叉树的节点删除和销毁

目录

节点删除的三种情况:

第一种情况:

第二种情况:

第三种情况

代码实现:

main函数

节点删除的三种情况:
节点删除总共分成三种情况:

第一种情况:
若为叶子节点则直接删除,如左图节点1,3 ,8或者右图的1,4,8。(若为单独一个根叶子要单独处理) 

若为单独一个根叶子

 

第二种情况:
若该节点,有一个节点,左或是右。因为只有一个节点,直接令祖父节点指向孙子节点,孙子节点的左右需要分开判断。如图中节点2(若该节点为根要单独处理) 

 

若该节点为根

 

 

第三种情况
若该节点含有两个子节点,一般的删除策略是用其右子树的最小结点代替待删除结点的数据,然后递归删除那个右子树最小结点。即将第三种情况转化为第二种情况。如下图所示,要删除结点2,则找到结点2的右子树的最小结点3并将其数据赋值给结点2,然后在删除结点3。

第三种情况的特殊情况分析(删除的节点为2,右节点5没有左节点。则把节点2换成节点5) 

 

 

代码实现:
main函数
//这里没有用栈和队列,前面写的函数这次用到的,以用递归为主,不然代码太过冗余

#include <iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
 
struct TreeNode
{
    TreeNode*_left;
    TreeNode*_right;
    int _data;
};
 
void midOrderITraverse(TreeNode * r) //递归,中序,左根右
{
    if(r)
    {
        midOrderITraverse(r->_left);
        printf("%d ",r->_data);
        midOrderITraverse(r->_right);
    }
}
 
//递归版插入
void insertBstRecusive(TreeNode** root ,int data)
{
    if((*root) == NULL)
    {
        (*root) =(TreeNode*)malloc(sizeof(TreeNode));
        (*root)->_data =data;
        (*root)->_left = (*root)->_right =NULL;
    }
    else if(data > (*root)->_data)
    {
        insertBstRecusive(&((*root)->_right),data);
    }
    else
    {
        insertBstRecusive(&((*root)->_left),data);
    }
}
 
//查找,递归版
TreeNode* searchBstRecursive(TreeNode* r,int find)
{
    if(r)
    {
        if(r->_data == find)
            return r;
        else if(r->_data > find)
            return searchBstRecursive(r->_left,find);
        else
            return searchBstRecursive(r->_right,find);
    }
}
 
//寻找最小值、最大值
TreeNode* getMinBst(TreeNode* r)
{
    if(r)
    {
        while(r->_left)
        {
            r=r->_left;
        }
        return r;
    }
    return NULL;
}
TreeNode* getMaxBst(TreeNode* r)
{
    if(r)
    {
        while(r->_right)
            r=r->_right;
        return r;
    }
    return NULL;
}
 
//查找父节点,迭代版
TreeNode* getParentBst(TreeNode*r,TreeNode * child)
{
    static TreeNode*parent = NULL;
    if(r)
    {
        if(r->_right == child || r->_left ==child)
            parent =  r;
        getParentBst(r->_left,child);
        getParentBst(r->_right,child);
    }
    return parent;
}
 
//删除节点
void deleteBst(TreeNode** r,TreeNode * pDel)
{
    TreeNode* t = *r;
    TreeNode * parent = getParentBst(t,pDel);
    TreeNode * minRight; //找到右节点为树的最小节点
    if(*r == NULL || pDel == NULL)
        return ;
    if(pDel->_left == NULL && pDel->_right == NULL) //第一种情况
    {
        if(*r == pDel)  //若删除的节点为根
        {
            free(t);
            *r = NULL;
            return;
        }
        if(parent->_left == pDel)
            parent->_left = NULL;
        else
            parent->_right = NULL;
        free(pDel);
        return;
    }
    else if(pDel->_left !=NULL && pDel->_right == NULL)//第二种
    {
        if(*r == pDel)
        {
            *r = pDel->_left; //这里 *r , t , pDel的_left 都可以
            free(pDel);
            return;
        }
        if(parent->_left == pDel)
            parent->_left = pDel->_left;
        else
            parent->_right = pDel->_left;
        free(pDel);
        return;
    }
    else if(pDel->_left == NULL && pDel->_right != NULL)//第二种
    {
        if(*r == pDel)
        {
            *r = pDel->_right;
            free(pDel);
            return;
        }
        if(parent->_left == pDel)
            parent->_left = pDel->_right;
        else
            parent->_right = pDel->_right;
        free(pDel);
        return;
    }
    else
    {
        //这里不讨论删除节点是否为根的情况
        //因为无论删除的是不是根节点,左右节点不为空,都需要替换来删除
        minRight = getMinBst(pDel->_right);
        pDel->_data = minRight->_data;
        parent = getParentBst(t,minRight);
 
        if(minRight == pDel->_right)
            parent->_right = minRight->_right;  //这里pDel的_right无论是否为空都可以
        else
            parent->_left = minRight->_right;
        free(minRight);
    }
}
 
//销毁树
void destroyBst(TreeNode* r)
{
    if(r)
    {
        destroyBst(r->_left);
        destroyBst(r->_right);
        free(r);
    }
}
 
int main()
{
     TreeNode *root=NULL;            //树的初始化
     insertBstRecusive(&root,30);     //利用例子建造树
     insertBstRecusive(&root,8);
     insertBstRecusive(&root,15);
     insertBstRecusive(&root,36);
     insertBstRecusive(&root,100);
     insertBstRecusive(&root,32);
 
     midOrderITraverse(root);
     putchar(10);
     TreeNode * ch = searchBstRecursive(root,36);
     if(ch == NULL)
         printf("no find");
     else
         cout<<ch->_data<<" ,find it"<<endl;
 
    deleteBst(&root,ch);
    midOrderITraverse(root);
 
    if(root == NULL)
        printf("Tree is empty");
 
    destroyBst(root);
    root = NULL; //main函数必须有,防止野指针
     return 0;
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值