二叉搜索树的插入、删除

1.插入

题目描述:
给定二叉搜索树(BST)的根节点和要插入树中的值,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 ,新值和原始二叉搜索树中的任意节点值都不同。

注意,可能存在多种有效的插入方式,只要树在插入后仍保持为二叉搜索树即可。 你可以返回 任意有效的结果 。

链接:https://leetcode-cn.com/problems/insert-into-a-binary-search-tree

思路分析:该树就为一颗二叉搜索树(bst),左边的比根节点都小,右边的比根节点都大。
在这里插入图片描述
插入的时候,该节点一定会新开辟一个节点,并插入在根节点的左边或者右边。

  1. 大于根节点,插入在右边。
  2. 小于根节点,插入在左边。

比如插入35:

在这里插入图片描述

比如插入18:

在这里插入图片描述

1.1 递归

代码:

class Solution {
public:
    TreeNode* insertIntoBST(TreeNode* root, int val) {
        if(root == nullptr)//为空,此时就可以插入了
        {
            TreeNode * p = new TreeNode(val);
            return p;
        }
        if(root->val > val)  //当前根节点值大于val则在左边插入
            root->left = insertIntoBST(root->left, val);
        if(root->val < val)//在右边插入
            root->right = insertIntoBST(root->right, val);
        return root;//插入之后,直接返回
    }
};

1.2 迭代

代码:

class Solution {
public:
    TreeNode* insertIntoBST(TreeNode* root, int val) {
        if(root == nullptr)
            return new TreeNode(val);
        TreeNode* p = root;
        while(p != nullptr)
        {
            if(p->val > val)//根节点值大,左边插入
            {
                if(p->left == nullptr)//p的左侧为空,可以插入了,因为小于根节点,则在左侧插入
                {
                    p->left = new TreeNode(val);
                    break;
                }
                p = p->left;//还不能插入,改变当前节点位置
            }
            else//根节点值小,右边插入
            {
                if(p->right == nullptr)//p的右侧为空,可以插入了,因为大于根节点,则在右侧插入
                {
                    p->right = new TreeNode(val);
                    break;
                }
                p = p->right;//还不能插入,改变当前节点位置
            }
        }
        return root;//返回
    }
};

2. 删除

给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。

一般来说,删除节点可分为两个步骤:

首先找到需要删除的节点;
如果找到了,删除它。
说明: 要求算法时间复杂度为 O(h),h 为树的高度。

链接:https://leetcode-cn.com/problems/delete-node-in-a-bst

bst的删除,不能直接释放该节点,否则该树就崩溃了。

  1. 第一种情况:在左边寻找最大值然后删除,两者值交换,然后删除
    在这里插入图片描述
    这样该树,仍然是一颗二叉搜索树

  2. 第二种情况:在右边寻找最小值然后删除,两者值交换
    在这里插入图片描述这样该树,仍然是一颗二叉搜索树。

注意的点:

  1. 要删除的节点,左右都不为空时,则分两种情况,删除左边最大值还是右边最小值
  2. 若有一边为空了,则可以进行删除了,当前节点删除,返回其另一边的节点

代码:

class Solution {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        if(root == nullptr)//当前为空,直接返回
            return nullptr;
        if(root->val > key)//大于该值,该值在左边,向左边找
            root->left = deleteNode(root->left, key);
        else if(root->val < key)//小于该值,该值在右边,向右边找
            root->right = deleteNode(root->right, key);
        else//找到了
        {
            if(root->left != nullptr && root->right != nullptr)//左右子树皆不为空
            {
                TreeNode* s = root->right;//第二种情况,去找右边最小的值
                while(s->left != nullptr)
                    s = s->left;
                root->val = s->val;//此时就找到了,右边最小的值,改变当前值
                root->right = deleteNode(root->right, root->val);//右边去删除右边的最小值
            }
            else//可以删除了
            {
                if(root->left != nullptr)//左不为空
                {
                    TreeNode* s = root;//
                    root = root->left;//改变当前位置
                    delete s;//释放节点,leetcode没要求删除,但为了写代码的习惯,建议删除
                }
                else//右可能为空,可能不为空,不重要,为空返回空即可
                {
                    TreeNode* s = root;
                    root = root->right;//改变当前位置
                    delete s;//释放节点,leetcode没要求删除,但为了写代码的习惯,建议删除
                }
            }
        }
        return root;//返回
    }
};
//第一种情况也给出
            if(root->left != nullptr && root->right != nullptr)
            {
                TreeNode* s = root->left;//去找左边最大值
                while(s->right != nullptr)
                    s = s->right;
                root->val = s->val;//找到了,改变值
                root->left = deleteNode(root->left, root->val);//左边去删除左边最大值
            }
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值