java实现二叉树的删除节点操作

树结构出现的非常早,是一种使用非常广泛的数据结构,有必要好好学一学。在学习到二叉树的相关操作时,二叉树的查询和搜索还好,比较简单,但是二叉树的删除操作对新手来说不太好理解。看不懂的时候,千万不要硬看,很容易放弃。用IDE工具debug一遍流程,基本就可以理解了。
下面看一下极客时间算法课上给的删除二叉树节点的例子。

private static void deleteTreeNode(TreeNode root, int val) {
        if (root == null) {
            return;
        }
        TreeNode p = root;
        //pp是p的父节点
        TreeNode pp = null;
        //找到待删除的节点
        while (p != null && p.val != val) {
            pp = p;
            if (val > p.val) {
                p = p.right;
            } else {
                p = p.left;
            }
        }
        //如果未找到,直接返回
        if (p == null) {
            return;
        }
        //下面开始进行删除节点p的操作,分三种情况
        //节点p只有1个根节点,没有子节点
        //节点p有1个子节点
        //节点p有2个子节点
        //删除操作的流程是:从待删除元素的右子节点开始找到右子节点中最小的元素,最小元素替换
        //p元素
        TreeNode minp = null;//右子树最小元素
        TreeNode mpp = null;//右子树最小元素的父节点
        //节点p有2个节点的情况
        if (p.left != null && p.right != null) {
            minp = p.right;
            //mpp is the parent node of the mp node
            mpp = p;
            while (minp.left != null) {
                mpp = minp;
                minp = minp.left;
            }
            //注意下面的这三步,p.val=minp.val以及pp=mpp的操作不只是操作2个节点的情况,待删除元素只有根节点、或者只有1个节点时,这几行代码也有用处,不要局限在这个部分,从整体上看
            p.val = minp.val;
            p = minp;
            pp = mpp;
        }
        //删除节点右子树最小节点的子节点
        TreeNode child;
        if (p.left != null) {
            child = p.left;
        } else if (p.right != null) {
            child = p.right;
        } else {
            child = null;
        }
        if (pp == null) {
			//说明是根节点被删除,直接将根节点置为null即可
            root = child;
        } else if (pp.left.val == p.val) {
        	//如果待删除元素只有一个左节点,直接将让待删除元素的父节点连接其子节点即可。
        	//同时,如果待删除元素有2个子节点,p=minp以及pp=mpp的赋值操作也会处理到2个节
        	//点的子节点指针重新指向的情况,所以这一步操作要结合上面的p=minp以及pp=mpp来
        	//看
            pp.left = child;
        } else {
            //解释同上
            pp.right = child;
        }
    }

不知道我描述的是不是清楚,如果不清楚的话,直接debug一遍,就啥都清楚了。转变成自己的话,理解起来要更清晰一点。上面的代码确实不容易看懂。下面附上测试数据的生成代码,可以用这个数据进行测试工作

private static TreeNode buildTreeNode() {
        TreeNode root = new TreeNode(4);
        TreeNode left1 = new TreeNode(2);
        TreeNode right1 = new TreeNode(6);
        TreeNode left2 = new TreeNode(1);
        TreeNode right2 = new TreeNode(3);
        TreeNode left3 = new TreeNode(5);
        TreeNode right3 = new TreeNode(12);
        TreeNode left4 = new TreeNode(8);
        TreeNode right4 = new TreeNode(13);
        TreeNode left5 = new TreeNode(7);
        TreeNode right5 = new TreeNode(10);
        TreeNode left6 = new TreeNode(9);
        root.left = left1;
        root.right = right1;
        left1.left = left2;
        left1.right = right2;
        right1.left = left3;
        right1.right = right3;
        right3.left = left4;
        right3.right = right4;
        left4.left = left5;
        left4.right = right5;
        right5.left = left6;
        return root;
    }
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值