ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

401,删除二叉搜索树中的节点

2021-06-14 23:58:15  阅读:193  来源: 互联网

标签:左子 right 删除 树中 二叉 401 root 节点 left


watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

I wanted to live deep and suck out all the marrow of life. 

我希望活得深刻,吸取生命中所有精华。

问题描述

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

 

示例:

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

key = 3

 

    5

   / \

  3   6

 / \   \

2   4   7

 

给定需要删除的节点值是 3,所以我们首先找到 3 这个节点,然后删除它。

 

一个正确的答案是 [5,4,6,2,null,null,7], 如下图所示。

 

    5

   / \

  4   6

 /     \

2       7

 

另一个正确答案是 [5,2,6,null,4,null,7]。

 

    5

   / \

  2   6

   \   \

    4   7

 

问题分析

二叉搜索树的特点是左子树的值都比他小,右子树的值都比他大,删除一个节点之后我们还要保证二叉搜索树的这个特点不变。如果要删除一个结点,我们先要找到这个节点,然后才能删除,但这里要分几种情况。

  • 如果要删除的节点是叶子节点,我们直接删除即可。

  • 如果删除的结点不是叶子节点,并且有一个子节点为空,我们直接返回另一个不为空的子节点即可。

  • 如果删除的结点不是叶子节点,并且左右子树都不为空,我们可以用左子树的最大值替换掉要删除的节点或者用右子树的最小值替换掉要删除的节点都是可以的。

 

这里使用递归的方式是最容易理解的,我们来看下代码

 1public TreeNode deleteNode(TreeNode root, int key) {
2    if (root == null)
3        return null;
4    //通过递归的方式要先找到要删除的结点
5    if (key < root.val) {
6        //要删除的节点在左子树上
7        root.left = deleteNode(root.left, key);
8    } else if (key > root.val) {
9        //要删除的节点在右子树上
10        root.right = deleteNode(root.right, key);
11    } else {
12        //找到了要删除的节点。
13        //如果左子树为空,我们只需要返回右子树即可
14        if (root.left == null)
15            return root.right;
16        //如果右子树为空,我们只需要返回左子树即可
17        if (root.right == null)
18            return root.left;
19        //说明两个子节点都不为空,我们可以找左子树的最大值,
20        //也可以找右子树的最小值替换
21
22        //这里是用右子树的最小值替换
23        //TreeNode minNode = findMin(root.right);
24        //root.val = minNode.val;
25        //root.right = deleteNode(root.right, root.val);
26
27        //这里是用左子树的最大值替换
28        TreeNode maxNode = findMax(root.left);
29        root.val = maxNode.val;
30        root.left = deleteNode(root.left, root.val);
31    }
32    return root;
33}
34
35//    找右子树的最小值
36//    private TreeNode findMin(TreeNode node) {
37//        while (node.left != null)
38//            node = node.left;
39//        return node;
40//    }
41
42//找左子树的最大值
43private TreeNode findMax(TreeNode node) {
44    while (node.right != null)
45        node = node.right;
46    return node;
47}

上面节点删除的时候我们使用左子树的最大值或者右子树的最小值替换都是可以的。其实我们还可以改一下,如果要删除结点左右子树只要有一个为空,我们就返回另一棵子树,如果都不为空,我们可以让左子树成为右子树最小结点的左子树或者让右子树成为左子树最大结点的右子树,我们来看下代码。

 1public TreeNode deleteNode(TreeNode root, int key) {
2    if (root == null)
3        return null;
4    if (root.val > key) {
5        //要删除的节点在左子树上
6        root.left = deleteNode(root.left, key);
7    } else if (root.val < key) {
8        //要删除的节点在右子树上
9        root.right = deleteNode(root.right, key);
10    } else {
11        //找到要删除的结点之后
12        if (root.left == null)
13            return root.right;
14        if (root.right == null)
15            return root.left;
16
17        /*
18        //左右子树都不为空,找到要删除结点右子树的最小值
19        TreeNode rightSmallest = root.right;
20        while (rightSmallest.left != null)
21            rightSmallest = rightSmallest.left;
22        //这个最小值对应的节点一定是没有左子树的,
23        // 如果有他肯定不是最小的,然后让删除结点的
24        //左子树成为这个最小值的左子树
25        rightSmallest.left = root.left;
26        //直接返回要删除结点的右子树
27        return root.right;
28         */
29
30        //左右子树都不为空,找到要删除结点左子树的最大值
31        TreeNode leftBig = root.left;
32        while (leftBig.right != null)
33            leftBig = leftBig.right;
34        //这个最大值对应的节点一定是没有右子树的,
35        // 如果有他肯定不是最大的,然后让删除结点的
36        //右子树成为这个最大值的右子树
37        leftBig.right = root.right;
38        //直接返回要删除结点的左子树
39        return root.left;
40    }
41    return root;
42}

 

总结

删除结点的时候并不一定要直接删除,在之前讲378,数据结构-7,堆的时候删除结点直接使用其他节点来替换掉要删除的结点即可。这里也是使用同样的方式,对于二叉搜索树节点的删除,我们可以用它左子树的最大值或者右子树的最小值来替换,如果没有左子树或者右子树那就更方便了。

 

 

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

399,从前序与中序遍历序列构造二叉树

388,先序遍历构造二叉树

372,二叉树的最近公共祖先

367,二叉树的最大深度

 

 

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

长按上图,识别图中二维码之后即可关注。

 

如果喜欢这篇文章就点个"赞"吧

标签:左子,right,删除,树中,二叉,401,root,节点,left
来源: https://blog.51cto.com/u_4774266/2902785

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有