删除排序二叉树的节点

LeetCode问题描述:

Given a root node reference of a BST and a key, delete the node with the given key in the BST. Return the root node reference (possibly updated) of the BST.

Basically, the deletion can be divided into two stages:

  1. Search for a node to remove.
  2. If the node is found, delete the node.

Note: Time complexity should be O(height of tree).

Example:

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

    5
   / \
  3   6
 / \   \
2   4   7

Given key to delete is 3. So we find the node with value 3 and delete it.

One valid answer is [5,4,6,2,null,null,7], shown in the following BST.

    5
   / \
  4   6
 /     \
2       7

Another valid answer is [5,2,6,null,4,null,7].

    5
   / \
  2   6
   \   \
    4   7

题目大意是说给定某一个排序二叉树(BST)和一个Key值,要求删除此排序二叉树中与Key值相等的节点,之后返回此BST的根节点。
分析如下:

一、查找节点:

这一步是最基础的,一般大家会想到利用BST的性质直接进行查找,但是在这里可能会有点问题(后面会讲到)。

二、删除节点:

分三种情况——该节点无子节点、该节点有1个子节点、该节点有2个子节点。

①无子节点:
在这种情况下,我们这需做一个判断——如果该节点为根节点,则直接返回null;
否则,对其父节点中该节点赋值null,并返回root(根节点)。

②有1个子节点:
判断——如果该节点为root节点,直接返回其子节点;否则,对其父节点中该节点赋值为该节点的子节点,并返回root。

③有2个子节点:
这种情况最复杂,先找到该节点右子树的最小节点,并将此最小节点与该节点进行值交换,然后删除找到的这个最小节点。
注:这里递归删除时会有一些问题,因为虽然原二叉树是BST,但将节点的值进行交换后,顺序改变,就不再是BST了,所以一中不应该使用BST的查找算法,而应该采用遍历查找

实现代码如下(Java):

class TreeNode{
    int val;//节点值
    TreeNode left;
    TreeNode right;
    TreeNode(int x){
        this.val = x;
    }

}

class Solution{
    //输出第level层的节点的值
    public int showTreeValueAtLevel(TreeNode node , int level){
        if(level < 0)
            return 0;//如果node为空或者level<0,直接结束
        else if(node == null){
            System.out.print("null ");
            return 0;
        }
        else if(level == 0 && node != null){
            System.out.print(node.val+" ");
            return 1;//level == 0时即为找到了此节点
        }
        return showTreeValueAtLevel(node.left, level-1)+showTreeValueAtLevel(node.right, level-1);
    }
    public void levelTravelsal(TreeNode node){
        int i;//遍历的层数
        for(i = 0;;i++){
            if(showTreeValueAtLevel(node, i)==0)//终止遍历条件
                break;
            System.out.println();
        }
    }
    public TreeNode deleteNode(TreeNode root, int key) {
        if(root == null)
            return null;
        TreeNode father = searchFatherNode(root, key);
        TreeNode desNode;//目标节点
        desNode = getDesNode(root, father, key);
        System.out.println("father:"+father);
        if(desNode == null){
            return root;
        }else{
                if(desNode.left == null && desNode.right == null){
                //目标节点存在且无子节点
                if(desNode == root)
                    return null;
                else if(father.left == desNode)
                    father.left = null;
                else 
                    father.right = null;
            }else if(desNode.left != null && desNode.right == null ){
                //目标节点存在且只有左节点
                if(desNode == root)//如果是根结点,直接返回其子节点
                    return desNode.left;
                desNode.val = desNode.left.val;
                if(father.left == desNode)
                    father.left = desNode.left;
                else
                    father.right = desNode.left;
            }else if(desNode.right != null && desNode.left == null){
                //目标节点存在且只有右节点
                if(desNode == root)//如果是根结点,直接返回其子节点
                    return desNode.right;
                desNode.val = desNode.right.val;
                if(father.left == desNode)
                    father.left = desNode.right;
                else
                    father.right = desNode.right;
            }else{
                //目标节点有左右子节点
//              System.out.println("currDesNode:"+desNode.val);
                TreeNode minNode = getMinNode(desNode.right);
//              System.out.println("minNode:"+minNode.val);
                Swap(desNode, minNode);
                return deleteNode(root, key);
            }
            return root;
        }
    }

    //交换两节点的值
    public void Swap(TreeNode node1, TreeNode node2){
        int temp = node1.val;
        node1.val = node2.val;
        node2.val = temp;
    }

    //从根结点出发,返回最小的节点
    public TreeNode getMinNode(TreeNode root){
        if(root.left != null)
            return getMinNode(root.left);
        return root;
    }

    //找出符合条件的节点的父节点
    public TreeNode searchFatherNode(TreeNode root, int key){
        if(root == null)
            return null;
        if(root.left != null && root.left.val == key)
            return root;
        else if(root.right != null && root.right.val == key)
            return root;
        //继续找
        TreeNode resNode;
        if(root.left != null){
            resNode = searchFatherNode(root.left, key);
            if(resNode != null)
                return resNode;
        }
        if(root.right != null){
            resNode = searchFatherNode(root.right, key);
            if(resNode != null)
                return resNode;
        }
        return null;
    }

    public TreeNode getDesNode(TreeNode root,TreeNode father, int key){
        if(father == null){
            if(root.val == key)//目标节点就是根结点
                return root;
            else return null;//目标节点不存在
        }else{
            //如果father不为空,则目标节点一定存在;
            if(father.left != null && father.left.val == key)
                return father.left;
            else
                return father.right;
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值