二叉树--删除二叉搜索树的结点

二叉树搜索树
删除(Delete)二叉搜索树上的任意一个节点
原理

我们将删除结点的情况 分为三种
1.NO child

  • 被删除节点是叶子结点 因为叶子结点没有孩子 可以直接删除
  • 我们只需要将结点释放内存在讲这个空地址 return 回去就好了
  • 在这里插入图片描述
    在这里插入图片描述
  1. One child
  • 结点只有一个孩子,无论是这个孩子是左孩子 还是右孩子
  • 因为只有一个孩子 我们只需要将 root(被删除的结点) = root->child
  • 指针root 移动到他自身唯一的孩子去 跳过这个被删除的结点 最后返回root->child 给root的父亲
  • 同时要先用一个临时变量temp 把root记录下来 最后free(temp) 释放内存空间
  • 在这里插入图片描述
  • 在这里插入图片描述
  1. Two child
  • 面对有两个孩子的结点, 我们应该将它转为成情况1 或者情况2
  • 我们找到 这个结点右子树的最小值 或者是左子树的最大值
  • 为什么要找到右子树的最小值? 因为右子树的最小值一定比这个根节点的左子树
    大 同时一定比根节点的右子树小, 而且 无论是最小值还是最大值一定都只有一个孩子
  • 这样一来我们将情况3 转换成情况2
  • 如果使用右子树的最小值
  • 首些 得到右子树最小值的节点 min ,再把根节点root->data = min->data
  • 替换掉root的值
  • 最后再把最小值的结点删除 因为是从右子树找到最小值 所以我们要以右子树为根去删除
  • root->right = Delete(root->right, min->data);
  • root的右子树中某个结点被删除了
  • 最后逐层返回

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

测试代码
#include<stdio.h>
#include<stdlib.h>

typedef struct BstNode{
    int data;
    struct BstNode* left;
    struct BstNode* right;
}BstNode;
BstNode* Insert(BstNode* root,int data);
BstNode* GetNewNode(int data);
int Search(BstNode* root, int data);
BstNode* FindMin(BstNode* root);
BstNode* Delete(BstNode* root, int data) ;
void PreOrder( BstNode* root);
int main()
{
    BstNode *Proot;  //The pointer is point to root node of Tree
    Proot = NULL;     //setting Tree as empty
    Proot = Insert(Proot,15);
    Proot = Insert(Proot,10);
    Proot = Insert(Proot,20);
    Proot = Insert(Proot,25);
    Proot = Insert(Proot,8);
    Proot = Insert(Proot,12);
    int number;
    printf("Enter number be searched\n");
    PreOrder( Proot); 
    Proot = Delete(Proot, 10);
    printf("\n");
     PreOrder( Proot); 
    
    return 0;
}

BstNode* GetNewNode(int data)
{
    BstNode* newNode = (BstNode*)malloc(sizeof(BstNode));  //申请一个Bstnode结构的变量 将指针指向这个变量
    (*newNode).data = data;  // 将数据给到结点
    newNode->left = NULL;  //子树指针为空
    newNode->right = NULL;
    return newNode;    //返回指针
}
BstNode* Insert(BstNode* root,int data)
{
    if( root == NULL){  //查看根节点是否为空  如果空就这这个指针指向一个新的结点
        root = GetNewNode(data);  
    }else if( data <= root->data){  //如果数据比结点小  将结点插入到左子树
        root->left = Insert(root->left, data);
    }else {
        root->right = Insert(root->right ,data); //否者数据比结点大  将结点插入到右子树
    }
    return root;
}
int Search(BstNode* root, int data)
{
      if(root == NULL) return 0; //0代表树空
      else if(root->data == data) return 1;
      else if( data <= root->data) return Search(root->left, data);
      else return Search(root->right, data);
      
}
BstNode* FindMin(BstNode* root)
{
    BstNode* current = root;
    while( current->left !=NULL)
    {
        current = current->left;
    }
    return current;
}

BstNode* Delete(BstNode* root, int data)  //根节点和要删除的数据
{
    if( root == NULL) return NULL;

    else if( data < root->data) root->left = Delete( root->left,data); //data 比 根节点要小 那么就去根的左子树去匹配   
    else if( data > root->data) root->right = Delete(root->right, data); //data 比根节点要大 去根的右子树寻找匹配项
    else  // 找到了匹配的结点了  要区分被删除的结点的子树个数 分三种 
    {
         // Case no child
         if( root->left == NULL && root->right == NULL)
             { 
              free(root);
              root = NULL ;
             }  
         // Case 2 One child
        else if( root->left == NULL)
        {
            BstNode* temp = root; //临时指针指向root 
            root = root->right;  //因为 只有一个右孩子 所有我们将结点前进 再把这个结点返回 
            free(temp);          // 把要删除的结点内存释放
                                // 这样子root指向的结点就被root->right 代替了
        }else if ( root->right ==NULL)
        {
            BstNode* temp = root; //临时指针指向root 
            root = root->left;  //因为 只有一个左孩子 所有我们将结点前进 再把这个结点返回 
            free(temp);         // 把要删除的结点内存释放
              // 这样子root指向的结点就被root->right 代替了
        }  // case 3 Two child
        else{
                BstNode* min = FindMin(root->right); // 从右子树寻找最小值 或者从左子树寻找最大值
                root->data = min->data; // 将被删除的结点data 替换成min的data
                root->right = Delete( root->right, min->data);
        }
    }
    return root;
}

void PreOrder( BstNode* root)
{
    if( root == NULL ) return ;
    else
    {
        printf("%5d",root->data);
        PreOrder(root->left);
        PreOrder(root->right);
    }
}

在这里插入图片描述

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值