代码随想录算法训练营17天 | ​​235. 二叉搜索树的最近公共祖先、701.二叉搜索树中的插入操作、450.删除二叉搜索树中的节点

题目链接:235. 二叉搜索树的最近公共祖先701.二叉搜索树中的插入操作450.删除二叉搜索树中的节点
文章链接:代码随想录

二叉树


1. 二叉搜索树的最近公共祖先

(待更新...)

//递归法

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(root == NULL) return root;

        //若p和q的节点值均小于当前节点值,说明p和q都在当前节点的左子树中,往左递归
        if(root -> val > p -> val && root -> val > q -> val) {
            TreeNode* left = lowestCommonAncestor(root -> left, p, q);
            if(left != NULL) return left;
        //若p和q的节点值均大于当前节点值,说明p和q都在当前节点的右子树中,往右递归
        } else if(p -> val > root -> val && q -> val > root -> val) {
            TreeNode* right = lowestCommonAncestor(root -> right, p, q);
            if(right != NULL) return right;
        }
        
        //以上两种条件都不符合,则当(p -> val <= root -> val && root -> val <= q -> val)
        //或(q -> val <= root -> val && root -> val <= p -> val)时,root就是最近公共祖先,直接返回
        return root;
    }
};
//迭代法

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        while(root != NULL) {
            if(root -> val > p -> val && root -> val > q -> val) 
                root = root -> left;
            else if(root -> val < p -> val && root -> val < q -> val)
                root = root -> right;
            else return root; 
        }

        return root;
    }
};

 2. 二叉搜索树中的插入操作

(待更新...)

 //递归法

class Solution {
public:
    TreeNode* insertIntoBST(TreeNode* root, int val) {
        //终止条件:遍历到空节点,这个位置就要插入新的节点
        if(root == nullptr) {
            TreeNode* node = new TreeNode(val);
            return node; //利用返回值完成新插入的节点与其父节点的赋值操作
        }

        //下一层将加入节点返回,本层用root->left或者root->right将其接住
        if(root -> val > val) root -> left = insertIntoBST(root -> left, val);
        else if(root -> val < val) root -> right = insertIntoBST(root -> right, val);

        return root;
    }
};
 //迭代法

class Solution {
public:
    TreeNode* insertIntoBST(TreeNode* root, int val) {
        TreeNode* node = new TreeNode(val); //待插入的新节点

        if(root == NULL) return node; //如果根节点为空,直接返回新节点

        TreeNode* parent = root; //父亲节点,记录遍历的上一个节点
        TreeNode* cur = root; //当前遍历的节点

        //遍历
        while(cur != NULL) {
            parent = cur;
            if(cur -> val > val) cur = cur -> left;
            else if(cur -> val < val) cur = cur -> right;
        }

        //遍历结束后,parent指向最后一个遍历的节点(也就是待插入新节点的父亲节点),cur此时为空
        //再做一次判断,完成新节点与父亲节点的赋值操作
        if(parent -> val > val) parent -> left = node;
        else parent -> right = node;

        return root;
    }
};

3. 删除二叉搜索树中的节点

(待更新...)

 /*
 以下面这个二叉树为例,描述二叉搜索树删除节点可能遇到的五种情况:
 第一种:遍历到空节点,说明没有找到要删除的节点
 第二种:要删除的节点在二叉树中左右都为空(即叶子节点),直接删除该节点(例如下图节点1)
 第三种:要删除的节点在二叉树中左不为空,右为空,此时删除该节点,并将其左孩子与其父亲节点衔接(例如下图节点2)
 第四种:要删除的节点在二叉树中左为空,右不为空,此时删除该节点,并将其右孩子与其父亲节点衔接(处理逻辑同上)
 第五种:要删除的节点在二叉树中左右均不为空,此时有两种处理逻辑,一是将左子树衔接到右子树上,二是将右子树衔接到左子树上(例如下图节点7)

          *原二叉树*

              3
           /     \
         2         7
       /         /   \
      1         5     9
               / \   / \
              4  6  8  10

         *第三种情况*

              3
           /     \
         1         7
                 /   \
                5     9
               / \   / \
              4  6  8  10

    *第五种情况* (解法一)                 *第五种情况* (解法二)  

              3                                     3
           /     \                               /     \
         2        9                            2         5
       /         / \                          /         /  \
      1         8  10                        1         4    6
               /                                             \
              5                                               9
             / \                                             / \
            4  6                                            8  10 
                 
*/
class Solution {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        //终止条件:
        //若根节点为空,则直接返回空
        //也可以作为第一种情况的处理方法:遍历到空节点,说明没有找到要删除的节点,直接返回空
        if(root == nullptr) return NULL;

        //找到了要删除的节点,接下来对可能出现的四种情况进行讨论
        if(root -> val == key) {
            //第二种:要删除的节点在二叉树中左右都为空(即叶子节点),直接删除该节点,返回空
            if(!root -> left && !root -> right) {
                //释放内存
                delete root;
                return NULL;
            //第三种:要删除的节点在二叉树中左不为空,右为空,此时删除该节点,并将其左孩子与其父亲节点衔接,处理方法是将其左孩子返回到上一层递归,注意要为删除的节点释放内存
            } else if(root -> left && !root -> right) {
                TreeNode* node = root -> left;
                //释放内存
                delete root;
                return node;
            //第四种:要删除的节点在二叉树中左为空,右不为空,此时删除该节点,并将其右孩子与其父亲节点衔接,处理方法是将其右孩子返回到上一层递归,注意要为删除的节点释放内存
            } else if(!root -> left && root -> right) {
                TreeNode* node = root -> right;
                //释放内存
                delete root;
                return node;
            //第五种:要删除的节点在二叉树中左右均不为空,此时采用第一种解法,即将左子树衔接到右子树上
            //方法是找到删除节点右子树上最左边的节点,然后将删除节点的左孩子(也就是其左子树的头节点)接上去
            //最后返回删除节点的右孩子作为新的根节点
            } else {
                TreeNode* cur = root -> right; //删除节点的右孩子
                while(cur -> left != nullptr) {
                    cur = cur -> left;         //找到删除节点右子树上最左边的节点
                }
                cur -> left = root -> left;    //将将删除节点的左孩子(也就是其左子树的头节点)接上去

                TreeNode* node = root -> right;//返回删除节点的右孩子作为新的根节点
                //释放内存
                delete root;        
                return node;
            }
        }

        if(root -> val > key) root -> left = deleteNode(root -> left, key);
        else if(root -> val < key) root -> right = deleteNode(root -> right, key);

        return root;
    }
};

 相关题目和后续提高:

提高:

普通二叉树的删除方式

“删除二叉搜索树中的节点”迭代法


心得:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值