数据结构——二叉排序树的删除操作(递归法)

1、被删除的节点是叶子节点
将双亲节点中相应的指针域的值改为空
在这里插入图片描述

2、被删除的节点只有左子树或右子树
将要删除的节点的双亲节点相应指针域的值指向被删除节点的左子树或者右子树
在这里插入图片描述

3、被删除节点既有左子树又有右子树
将左子树中的最大值或者右子树中的最小值代替该节点
在这里插入图片描述
代码如下:

typedef struct TreeNode{
    int data;
    struct TreeNode *left,*right;
}TreeNode,*BiTNode;//定义了TreeNode结构体和结构体指针BiTNode
int Delete(BiTNode *rootPtr){//传入的参数为二级结构体指针
    BiTNode root,node;
    if((*rootPtr)->right == NULL){//右子树为空,则重接左子树
        root = *rootPtr;
        *rootPtr = (*rootPtr)->left;
        free(root);
    }else if((*rootPtr)->left == NULL){//左子树为空,则重接右子树
        root = *rootPtr;
        *rootPtr = (*rootPtr)->right;
        free(root);
    }else{  //左右子树均不为空
        root = *rootPtr;
        node = (*rootPtr)->left;
        while(node->right){//找到要删除节点左子树的最右节点,即左子树的最大值
            root = node;
            node = node->right;
        }
        (*rootPtr)->data = node->data;
        if(root != *rootPtr){
            root->right = node->left;//重接root的右子树
        }else{
            root->left = node->left;//重接root的左子树
        }
        free(node);
    }
    return TRUE;
}
int DeleteTreeNode(BiTNode *root, int data){//第一个参数root为二级指针
    if(*root == NULL){//空树直接返回
        return FALSE;
    }else{  //寻找数据为data的节点二叉树节点
        if(data == (*root)->data){
            return Delete(root);//找到就执行删除节点的操作
        }else if(data < (*root)->data){
            return DeleteTreeNode(&(*root)->left, data);//要找的数据小,往左子树找
        }else{
            return DeleteTreeNode(&(*root)->right, data);//要找的数据大,往右子树找
        }
    }
}

或者直接使用二级结构体指针

typedef struct TreeNode{
    int data;
    struct TreeNode *left,*right;
}TreeNode;
int Delete(TreeNode** rootPtr){//我们想修改TreeNode*类型的值,因此需传入二级指针TreeNode**才能修改
    TreeNode * root,*node;
    if((*rootPtr)->left == NULL){
        root = *rootPtr;
        *rootPtr = (*rootPtr)->left;
        free(root);
    }else if((*rootPtr)->right == NULL){
        root = *rootPtr;
        *rootPtr = (*rootPtr)->left;
        free(root);
    } else{
        root = *rootPtr;
        node = (*rootPtr)->left;
        while(node->right != NULL){
            root = node;
            node = node->right;
        }
        (*rootPtr)->data = node->data;
        if(*rootPtr != root){//判断while循环是否执行
            root->right = node->left;
        }else{
            root->left = node->left;
        }
        free(node);
    }
    return TRUE;
}
int DeleteTreeNode(BiTNode *root, int data){//第一个参数root为二级指针
    if(*root == NULL){//空树直接返回
        return FALSE;
    }else{  //寻找数据为data的节点二叉树节点
        if(data == (*root)->data){
            return Delete(root);//找到就执行删除节点的操作
        }else if(data < (*root)->data){
            return DeleteTreeNode(&(*root)->left, data);//要找的数据小,往左子树找
        }else{
            return DeleteTreeNode(&(*root)->right, data);//要找的数据大,往右子树找
        }
    }
}

为什么在执行完while循环后需要判断(*rootPtr )是否等于 root?主要目的是为了判断while循环是否执行,例如,当删除节点为12时,则需要执行else语句。
在这里插入图片描述

完整代码如下:

#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
typedef struct TreeNode{
    int data;
    struct TreeNode *left,*right;
}TreeNode,*BiTNode;
TreeNode* InsertNode(TreeNode* root,int data){//排序二叉树中插入元素
    if(!root){
        root = (TreeNode*)malloc(sizeof(TreeNode));
        root->data = data;
        root->right = NULL;
        root->left = NULL;
        return root;
    }else{
        if(root->data > data){
            root->left = InsertNode(root->left,data);
        }else if(root->data < data){
            root->right = InsertNode(root->right,data);
        }else if(root->data == data){
            return root;
        }
    }
    return root;
}
void InOrderTree(TreeNode* root){//中序遍历二叉树
    if(root == NULL){
        return;
    }
    InOrderTree(root->left);
    printf("%d->",root->data);
    InOrderTree(root->right);
}
int Delete(BiTNode *rootPtr){
    BiTNode root,node;
    if((*rootPtr)->right == NULL){//右子树为空,则重接左子树
        root = *rootPtr;
        *rootPtr = (*rootPtr)->left;
        free(root);
    }else if((*rootPtr)->left == NULL){//左子树为空,则重接右子树
        root = *rootPtr;
        *rootPtr = (*rootPtr)->right;
        free(root);
    }else{  //左右子树均不为空
        root = *rootPtr;
        node = (*rootPtr)->left;
        while(node->right){//找到要删除节点左子树的最右节点,即左子树的最大值
            root = node;
            node = node->right;
        }
        (*rootPtr)->data = node->data;
        if(root != *rootPtr){
            root->right = node->left;//重接root的右子树
        }else{
            root->left = node->left;//重接root的左子树
        }
        free(node);
    }
    return TRUE;
}
int DeleteTreeNode(BiTNode *root, int data){//第一个参数root为二级指针
    if(*root == NULL){//空树直接返回
        return FALSE;
    }else{  //寻找数据为data的节点二叉树节点
        if(data == (*root)->data){
            return Delete(root);//找到就执行删除节点的操作
        }else if(data < (*root)->data){
            return DeleteTreeNode(&(*root)->left, data);//要找的数据小,往左子树找
        }else{
            return DeleteTreeNode(&(*root)->right, data);//要找的数据大,往右子树找
        }
    }
}
int main() {
    int data[11] = {38,12,56,6,34,40,98,3,13,78,17};
    TreeNode* root = NULL;
    for(int i = 0; i < (sizeof(data)/sizeof (data[0]));i++){
        printf("第%d次插入的元素为:%d\n",i+1,data[i]);
        root =InsertNode(root,data[i]);
    }
    printf("\n");
    InOrderTree(root);
    printf("END\n");
    DeleteTreeNode(&root,12);
    InOrderTree(root);
    printf("END\n");
    DeleteTreeNode(&root,34);
    InOrderTree(root);
    printf("END\n");
    DeleteTreeNode(&root,40);
    InOrderTree(root);
    printf("END\n");
    DeleteTreeNode(&root,98);
    InOrderTree(root);
    printf("END\n");
    DeleteTreeNode(&root,78);
    InOrderTree(root);
    printf("END\n");
     DeleteTreeNode(&root,3);
    InOrderTree(root);
    printf("END\n");
     DeleteTreeNode(&root,6);
    InOrderTree(root);
    printf("END\n");
     DeleteTreeNode(&root,13);
    InOrderTree(root);
    printf("END\n");
     DeleteTreeNode(&root,17);
    InOrderTree(root);
    printf("END\n");
     DeleteTreeNode(&root,56);
    InOrderTree(root);
    printf("END\n");
    DeleteTreeNode(&root,38);
    InOrderTree(root);
    printf("END\n");


    return 0;
}

程序运行结果为:

1次插入的元素为:382次插入的元素为:123次插入的元素为:564次插入的元素为:65次插入的元素为:346次插入的元素为:407次插入的元素为:988次插入的元素为:39次插入的元素为:1310次插入的元素为:7811次插入的元素为:17

3->6->12->13->17->34->38->40->56->78->98->END
3->6->13->17->34->38->40->56->78->98->END
3->6->13->17->38->40->56->78->98->END
3->6->13->17->38->56->78->98->END
3->6->13->17->38->56->78->END
3->6->13->17->38->56->END
6->13->17->38->56->END
13->17->38->56->END
17->38->56->END
38->56->END
38->END
END
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

karwen2020

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值