leetcode 450. 删除二叉搜索树中的节点 c语言实现

如题:

给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。
一般来说,删除节点可分为两个步骤:
首先找到需要删除的节点;
如果找到了,删除它。
说明: 要求算法时间复杂度为 O(h),h 为树的高度。

示例:
root = [5,3,6,2,4,null,7]
key = 3

    5
   / \
  3   6
 / \   \
2   4   7

给定需要删除的节点值是 3,所以我们首先找到 3 这个节点,然后删除它。
一个正确的答案是 [5,4,6,2,null,null,7], 如下图所示。

    5
   / \
  4   6
 /     \
2       7
另一个正确答案是 [5,2,6,null,4,null,7]。
    5
   / \
  2   6
   \   \
    4   7

简单说就是二叉搜索树的删除操作,难度为中等,这个是二叉搜索树的基本操作,掌握了就很简单了。

删除一个节点后要保持原有二叉树性质,根据节点自身的情况有三种情况需要处理

如果节点没有左右子树,则可以直接删除。
如果节点只有左子树或者右子树,则可以直接让子树替代自己。
如果同时存在左右节点,我们知道中序遍历二叉树得到有序数列,这时候有两种操作方式,一种是使用直接前驱替代待删节点,一种是使用直接后继替代待删节点。两种方式操作逻辑一致,仅仅方向不同。
3.1 设待删节点为delte, 如果采用直接前驱替代,这时候搜索节点左子树最右边的点s(s没有右子树),这时候有两种情况,一种是s本身就是待删节点的左子树,即s的父节点等于delte,这时候令

delte->left = s->left;delte->val = s->val;即可。

如果s的父节点p不等于delte,这时候需要将s的左子树变为p的右子树即可。
整个代码也比较简单理解:

//直接前驱替代
p = delte; s = delte->left;
while (s->right){p = s; s = s->right;}
dlete->val = s->val;
if (p == delte) delte->left = s->left;
else p->right = s->left;
free(s);

如果使用直接后继替代delte的话,这时候是搜索delte的右子树中最左边的元素s,同样存在两种情况,s的父节点p等于delte或者不等于,处理上和直接前驱类似。

//直接后继替代
p = delte; s = delte->right;
while (s->left){p = s; s = s->left;}
dlete->val = s->val;
if (p == delte) delte->right = s->right;
else p->left = s->right;
free(s);

下面是直接后继替代的代码:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

struct TreeNode* deleteBST(struct TreeNode* delte)
{
    struct TreeNode *p, *t;
    
    if (!delte->right)
    {
        //只有左孩子的情况
        t = delte; delte = delte->left;
    }
    else if (!delte->left)
    {
        //只有右孩子的情况        
        t = delte; delte = delte->right; 
    }
    else
    {
        //左右孩子都有,从右子树搜索其直接后继,即最左边的元素
        p = delte; t = p->right;
        while (t->left){
            p = t; t = t->left;
        }
        delte->val = t->val;
        if (p == delte)
            delte->right = t->right;
        else
            p->left = t->right;
    }
    
    free(t);
    return delte;
}

struct TreeNode* deleteNode(struct TreeNode* root, int key){
    if (!root)  return root;
    
    if (root->val == key)
        root = deleteBST(root);
    else if (root->val > key)
        root->left = deleteNode(root->left, key);
    else
        root->right = deleteNode(root->right, key);
    
    return root;
}

参考资料:

1. 数据结构 : C语言版/ 严蔚敏,吴伟民编著

2. 算法导论

=============================================================================================

Linux应用程序、内核、驱动开发交流讨论群(745510310),感兴趣的同学可以加群讨论、交流、资料查找等,前进的道路上,你不是一个人奥^_^。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值