二叉搜索树中删除一个结点(递归&非递归)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hansionz/article/details/81988752
1.思路

思路:在链式结构中,要删除一个结点,我们常规的做法是找到要删除结点的前一个结点,把它的和一个结点,挂在前一个结点上,但是对于二叉搜索树,既要删除一个结点,又要满足二叉搜索树的性质,是相对于比较难的。

二叉搜索树的删除大致分为以下类:
这里写图片描述

对于以上的四类要删除的结点,其实我们还可以在具体一些,将一二三类归在一起,第四类是一类。

下面是两类删除结点的方法
这里写图片描述

2.代码实现
  • 非递归实现
//删除一个结点(删除成功返回1,失败返回0)
int BSTreeRemove(BSTreeNode** root, BSTDataType x)
{
    assert(root);

    BSTreeNode* cur = *root;
    BSTreeNode* parent = NULL;//记录要删除结点的父节点

    while (cur)
    {
        //1.寻找要删除的结点
        if (cur->_data > x)
        {
            parent = cur;
            cur = cur->_left;
        }
        else if (cur->_data < x)
        {
            parent = cur;
            cur = cur->_right;
        }
        //2.此时cur指向要删除结点,parent指向要删除结点的父亲
        else
        {
            //①要删除结点的左孩子为空或者右孩子为空
            if (cur->_left == NULL)
            {
                //如果要删除的结点是根结点并且左孩子为空,替换根节点为右树根节点
                if (parent == NULL)
                {
                    *root = cur->_right;
                    free(cur);
                }
                //不是根节点,则直接判断调整指向
                else
                {
                    if (cur == parent->_left)
                    {
                        parent->_left = cur->_right;
                        free(cur);
                    }
                    else
                    {
                        parent->_right = cur->_right;
                        free(cur);
                    }
                }
            }
            else if (cur->_right == NULL)
            {
                //如果要删除的结点是根结点并且右孩子为空,替换根节点为左树根节点
                if (parent == NULL)
                {
                    *root = cur->_left;
                    free(cur);
                }
                //不是根节点,则直接判断调整指向
                else
                {
                    if (cur == parent->_left)
                    {
                        parent->_left = cur->_left;
                        free(cur);
                    }
                    else
                    {
                        parent->_right = cur->_left;
                        free(cur);
                    }
                }
            }
            //②要删除结点的左右孩子都不为空(替换删除法)
            else
            {
                BSTreeNode* repalce = cur->_right;
                //找到要替换的结点(要删除结点右树最左边的那个结点就是替换结点)
                while (repalce->_left)
                {
                    repalce = repalce->_left;
                }
                //替换数据
                cur->_data = repalce->_data;
                //递归删除替换结点
                BSTreeRemove(&cur->_right, repalce->_data);
            }
            return 1;
        }
    }
    return 0;
}
  • 递归实现
//删除一个结点(成功返回1,失败返回0)
int BSTreeRemoveR(BSTreeNode** root, BSTDataType x)
{
    assert(root);
    //树为空,删除失败
    if ((*root) == NULL)
    {
        return 0;
    }
    //要删除的数小于根结点的数,说明要删除的结点在左树
    if ((*root)->_data > x)
    {
        BSTreeRemoveR(&(*root)->_left, x);
    }
    //要删除的数大于根结点的数,说明要删除的结点在右树
    else if ((*root)->_data < x)
    {
        BSTreeRemoveR(&(*root)->_right, x);
    }
    //*root一定为要删除的结点
    else
    {
        //记录要释放的结点
        BSTreeNode* del = *root;
        //1.左子树为空或者右子树为空
        if ((*root)->_left == NULL)
        {
            *root = (*root)->_right;
            free(del);
        }
        else if ((*root)->_right == NULL)
        {
            *root = (*root)->_left;
            free(del);
        }
        //2.左右子树都不为空(替换删除法)
        else
        {
            BSTreeNode* repalce = (*root)->_right;
            while (repalce->_left)
            {
                repalce = repalce->_left;
            }
            (*root)->_data = repalce->_data;
            BSTreeRemoveR(&(*root)->_right, repalce->_data);
        }
        return 1;
    }
}

猜你喜欢

转载自blog.csdn.net/hansionz/article/details/81988752