树结构出现的非常早,是一种使用非常广泛的数据结构,有必要好好学一学。在学习到二叉树的相关操作时,二叉树的查询和搜索还好,比较简单,但是二叉树的删除操作对新手来说不太好理解。看不懂的时候,千万不要硬看,很容易放弃。用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;
}