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

二叉搜索树节点的删除较节点的插入和查找难以理解,涉及到以下情况:

节点为空时直接返回false;

    if (_root == NULL)
        {
            return false;
        }

有一个节点的时候,判断要删除的值是否和节点的权值相等,相等删除并返回true;不想等删除失败返回false;

    if (_root->_left == NULL&&_root->_right == NULL)
        {
            if (_root->_key == key)
            {
                delete _root;
                _root = NULL;
                return true;
            }
            return false;
        }

当树的节点众多时,首先找到需要删除节点cur的位置,记录节点的父亲节点parent

1.当cur的左子树为空的时候

要删除节点cur的parent节点为空,其实删除的就是这棵树的根节点,让cur的右节点作为根节点,delete掉cur,置空。

这里写图片描述

删除节点cur的parent不为空

cur在parent的左子树:
这里写图片描述
cur在parent的右子树:
这里写图片描述

if (cur->_left == NULL)
{
    del = cur;
    if (parent == NULL)
    {
        _root = cur->_right;
        delete del;
        del = NULL;
        return true;
    }
    if (parent->_left == cur)
    {
        parent->_left = cur->_right;
        delete del;
        del = NULL;
        return true;
    }
    else if (parent->_right == cur)
    {
        parent->_right = cur->_right;
        delete del;
        del = NULL;
        return true;
    }
}

2.当cur的右子树为空的时候

要删除节点cur的parent节点为空,其实删除的就是这棵树的根节点,让cur的左节点作为根节点,delete掉cur,置空。

这里写图片描述

删除节点cur的parent节点不为空的时候

cur节点在parent的左子树:
这里写图片描述

cur节点在parent的右子树:
这里写图片描述

else if (cur->_right == NULL)
{
    del = cur;
    if (parent == NULL)
    {
        _root = cur->_left;
        delete del;
        del = NULL;
        return true;
    }
    if (parent->_left == cur)
    {
        parent->_left = cur->_left;
        delete del;
        del = NULL;
        return true;
    }
    else if (parent->_right == cur)
    {
        parent->_right = cur->_left;
        delete del;
        del = NULL;
        return true;
    }
}

3.当左右子树都不为空的时候
这里写图片描述
这里写图片描述

if (cur->_left != NULL&&cur->_right != NULL)
{
    del = cur;
    Node* sub = cur->_right;
    Node* sub_parent = cur;
    while (sub->_left)
    {
        sub_parent = sub;
        sub = sub->_left;
    }
    cur->_key = sub->_key;
    if (sub_parent->_right == sub)
    {
        sub_parent->_right = sub->_right;
    }
    else
    {
        sub_parent->_left = sub->_right;
    }
    delete sub;
    sub = NULL;
    return true;
}

递归代码:

  void Remove_R(const T& key)
    {
        _Remove_R(_root, key);
    }
    bool _Remove_R(Node*& root, const T& key)
    {
        if (root == NULL)
        {
            return false;
        }
        if (root->_left == NULL&&root->_right == NULL)
        {
            if (root->_key == key)
            {
                delete root;
                root = NULL;
                return true;
            }
        }
        //先找到要删除的节点
        if (root->_key > key)
        {
            _Remove_R(root->_left, key);
        }
        else if (root->_key < key)
        {
            _Remove_R(root->_right, key);
        }
        else
        {
            Node* del = NULL;
            if (root->_left == NULL)
            {
                del = root;
                root = root->_right;
                delete del;
            }
            else if (root->_right == NULL)
            {
                del = root;
                root = root->_left;
                delete del;
            }
            else if (root->_left != NULL&&root->_right != NULL)
            {
                Node* subright = root->_right;
                while (subright->_left)
                {
                    subright = subright->_left;
                }
                root->_key = subright->_key;
//将右子树的最左节点和root节点的权值换了之后,需要删除的点替换成右子树的最左节点
//再递归调用一次函数,将右子树的根节点和需要删除的权值传进去,即可删除。
                _Remove_R(root->_right, subright->_key);
            }
        }
        return false;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值