Java中 递归删除树结构信息 递归删除树节点_删除结点


题解:

递归三部曲:

1、确定递归函数的参数和返回值

//返回值为删除结点后的树的根
TreeNode* deleteNode(TreeNode* root, int key)

2、确定递归终止条件

遍历到空结点返回

3、确定单层递归逻辑

删除结点所遇情况(找到):

(1)删除结点为叶子结点,直接删除,返回NULL

(2)删除结点的左孩子为空,右孩子不为空,右孩子补位 返回右孩子

(3)删除结点的右孩子为空,左孩子不为空,左孩子补位,返回左孩子

(4)删除结点的左右孩子均不为空,将删除结点的左子树头结点放到删除结点的右子树的最左面结点的左孩子上,返回删除结点的右孩子

然后根据目标值递归左右子树删除

示例:

Java中 递归删除树结构信息 递归删除树节点_结点_02


删除元素7后:

Java中 递归删除树结构信息 递归删除树节点_删除结点_03

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        //遍历到空 返回
        if(root == NULL){
            return NULL;
        }
        //单层递归逻辑
        //找到删除结点
        if(root->val == key){
            //(1)删除结点为叶子结点
            if(root->left==NULL && root->right == NULL){
                //直接删除  返回空即可
                return NULL;
            //(2)左空右不空 右孩子补位 
            }else if(root->left == NULL && root->right!=NULL){
                return root->right;
            //(3)左不空右空 左孩子补位 
            }else if(root->left!=NULL && root->right==NULL){
                return root->left;
            //左右均不空
            }else{
                TreeNode* node = root->right;
                while(node->left){
                    node = node->left;
                }
                //node即为右子树最左面结点的左孩子 将删除结点的左子树作为其左子树
                node->left = root->left;
                //把root结点保存一下 下面删除
                TreeNode* temp = root;
                //右孩子作为新root
                root = root->right;
                //释放结点内存
                delete temp;
                return root;
            }
        }
        //递归删除
        if(root->val>key){
            //删除结点在左子树
            root->left =  deleteNode(root->left,key);
        }
        //否则在右子树
        root->right = deleteNode(root->right,key);
        return root;
    }
};

迭代法:处理逻辑同上,增加一个pre记录删除结点的父结点 用于删除

class Solution {
public:
    //删除结点操作
    TreeNode* deleteOneNode(TreeNode* target){
        //(1)删除结点为叶子结点 或者左孩子为空 右孩子不为空
        //即左孩子为空 就返回右孩子
        if(target->left==NULL){
            return target->right;
        }
        //左不空 右空
        if(target->right == NULL){
            return target->left;
        }
        //左右不空
        TreeNode* node = target->right;
        while(node->left){
            node = node->left;
        }
        //node为target右子树的最左面的左孩子
        node->left = target->left;
        TreeNode* temp = target;
        //返回目标的右孩子
        target = target->right;
        delete temp;
        return target;
    }
    TreeNode* deleteNode(TreeNode* root, int key) {
        //为空 返回
        if(root == NULL){
            return NULL;
        }
        //迭代法
        TreeNode* cur  = root;
        //记录cur的父结点 用来删除cur
        TreeNode*pre = NULL;
        //寻找目标结点
        while(cur){
            if(cur->val == key){
                //跳出循环去做删除
                break;
            }
            //更新父结点
            pre = cur;
            if(cur->val>key){
                cur = cur->left;
            }else{
                cur = cur->right;
            }
        }
        //如果删除根节点
        if(pre == NULL){
            return deleteOneNode(cur);
        }
        //删除左孩子还是右孩子
        if(pre->left && pre->left->val == key){
            //删除左孩子
            pre->left = deleteOneNode(cur);
        }
        //删除右孩子
        if(pre->right && pre->right->val == key){
            pre->right = deleteOneNode(cur);
        }
        return root;
    }
};