设待测删除结点为cur,待删除结点的双亲结点为parent
分以下3种情况:
-
cur.left == null
- cur是root,则root = cur.right
- cur不是root,cur是parent.left,则parent.left = cur.right
- cur不是root,cur是parent.right,则parent.right = cur.right
-
cur.right == null
- cur是root,则root = cur.left
- cur不是root,cur是parent.left,则parent.left = cur.left
- cur不是root,cur是parent.right,则parent.right = cur.left
-
cur.left != null && cur.right !=null
替罪羊的删除方式:
在待删除结点的左边找最大的,右边找最小的。
实现代码如下:
public void remove(int val) {
if(root == null) return;
BSNode cur = root;
BSNode parent = null;
while (cur != null) {
if(cur.val == val) {
removeNode(parent,cur,val);
return;
}else if(cur.val < val) {
parent = cur;
cur = cur.right;
}else {
parent = cur;
cur = cur.left;
}
}
}
/**
* 删除二叉搜索树的节点
* @param parent
* @param cur
* @param val
*/
public void removeNode(BSNode parent,BSNode cur,int val) {
if(cur.left == null) {
if (cur ==root){
root = cur.right;
}else if (parent.left = cur){
parent.left=cur.right;
}else {
parent.right = cur.right;
}else if(cur.right == null) {
if (cur ==root){
root =cur.left;
}
}else if (parent.left = cur){
parent.left=cur.left;
}else {
parent.right=cur.left;
}
}else {
BSNode targetParent = cur;
BSNode target = cur.right;
while ( target.left !=null){
targetParent = target;
target = target.left;
}
//target指向的结点就是右边的最小值
cur.val =target.val;
if(target == targetParent.left){
targetParent.left = target.right;
}else {
targetParent.right =target.right;
}
}
}