二叉搜索树 | 二叉搜索树的删除操作

问题:删除二叉搜索树中的节点

问题链接
在这里插入图片描述
在这里插入图片描述

解题思路

通过二叉搜索树的性质对待删除节点进行定位,设待删除节点为x则有一下两种情况

  • 情况一:x有两个孩子
  • 情况二:x至多只有一个孩子
    当x有两个孩子时我们要用x的前驱节点或者x的后继节点替代x,将其值赋给x,然后删除x的前驱或者后继节点,此时就是情况二,对于情况二,如果x没孩子,直接将x删除,如果x有一个孩子,则将x的那个孩子链接到x的父节点上即可。

C++代码

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        if(!root) return NULL;
        TreeNode *parent = NULL, *x = root;//parent记录x的父节点,x表示待删除的点
        while(x && x->val != key){//找到待删除的点
            parent = x;//更新x的父节点
            if(x->val < key)//在x的右子树中
                x = x->right;
            else//在x的左子树中
                x = x->left;
        }
        if(!x) return root;//没找到,返回根节点

//x是要被删除的点,如果x只有至多一个孩子则可以删除,否则需要用x的前驱或者后继节点替代它,即将x的前驱节点的值赋给x即可
//x的前驱节点:x的左子树中的最大节点
//x的后继节点:x的右子树中的最小节点  
//此次我们用x的前驱节点
        
        TreeNode *y = x;//y表示真正要被删除的节点,初始为x
        if(x->left && x->right){//如果x有两个孩子,则用x的前驱节点替代x
            parent = y;
            y = x->left;
            while(y->right){
                parent = y;
                y = y->right;
            }
        }
        //此时y是待删除的节点且之多只有一个孩子

        if(!y->left && !y->right){ //情况一:y没有孩子,直接将y删掉
            if(parent){//删除y之前要将parent对应的指针设为NULL
                if(y->val < parent->val)
                    parent->left = NULL;
                else
                    parent->right = NULL;
            }
            if(!parent) root = NULL;//如果parent为NULL,说明删除的是root,令root为NULL
        }
        else{ //情况二:y有一个孩子
            TreeNode *child;
            if(y->left) child = y->left;
            if(y->right) child = y->right;
            if(parent){//确定child是parent的哪个孩子
                if(parent->val < child->val)
                    parent->right = child;//child是parent的右孩子
                else 
                    parent->left = child;//child是parent的左孩子
            }
            if(!parent) root = child;//parent为NULL,说明删除的是root,那么child成为新的根节点
        }
        if(y != x) x->val = y->val;//如果x和y不是同一个节点,则y是x的前驱节点,将y的值赋给x
        delete y;//释放y所占的空间
        return root;//返回根节点
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值