1.插入
题目描述:
给定二叉搜索树(BST)的根节点和要插入树中的值,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 ,新值和原始二叉搜索树中的任意节点值都不同。
注意,可能存在多种有效的插入方式,只要树在插入后仍保持为二叉搜索树即可。 你可以返回 任意有效的结果 。
思路分析:该树就为一颗二叉搜索树(bst),左边的比根节点都小,右边的比根节点都大。
插入的时候,该节点一定会新开辟一个节点,并插入在根节点的左边或者右边。
- 大于根节点,插入在右边。
- 小于根节点,插入在左边。
比如插入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的删除,不能直接释放该节点,否则该树就崩溃了。
-
第一种情况:在左边寻找最大值然后删除,两者值交换,然后删除
这样该树,仍然是一颗二叉搜索树 -
第二种情况:在右边寻找最小值然后删除,两者值交换
这样该树,仍然是一颗二叉搜索树。
注意的点:
- 要删除的节点,左右都不为空时,则分两种情况,删除左边最大值还是右边最小值
- 若有一边为空了,则可以进行删除了,当前节点删除,返回其另一边的节点
代码:
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);//左边去删除左边最大值
}