在BST中删除元素e
- 将问题转化成递归问题:在以node为根的BST中删除元素e,并返回新BST的根;
- 规模更小的同一个问题是:在以node的左孩子为根的BST中删除元素e,在以node的右孩子为根的BST中删除元素e:
- 如果e.compareTo(node.e) < 0, 在以node的左孩子为根的BST中删除元素e;
- 如果e.compareTo(node.e) > 0,在以node的右孩子为根的BST中删除元素e;
- 不能再缩小的基本问题是:对node的情况分类讨论:
- 如果node == null,那么以node为根的BST中没有e;
- 如果e.compareTo(node.e) == 0,那么node就是要删除的元素:
- 如果node没有左孩子,那么以node的右孩子为根的BST就是删除后的结果;
- 如果node没有右孩子,那么以node的左孩子为根的BST就是删除后的结果;
- 如果既有左孩子又有右孩子,采用Hibbard Deletion方法合并node的左右子树:
- 找到node的后继successor(右子树中最小的元素);
- 删除node右子树中最小的元素,并将结果连接到successor.right;
- 将successor.left指向node.left;
- 让node断开和左右子树的联系,即node.left = node.right = null;
- successor即为node的左右子树合并后根,将successor返回;
- 注意:不能再缩小的基本问题的代码,不一定写在递归方法的最前面,当然建议是这样写的;
// 从二分搜索树中删除元素为e的节点
public void remove(E e){
root = remove(root, e);
}
// 删除掉以node为根的二分搜索树中值为e的节点, 递归算法
// 返回删除节点后新的二分搜索树的根
private Node remove(Node node, E e){
if(node == null)
return null;
if(e.compareTo(node.e) < 0){
node.left = remove(node.left, e);
return node;
}
else if(e.compareTo(node.e) > 0){
node.right = remove(node.right, e);
return node;
}
else{ // e.compareTo(node.e) == 0
// 待删除节点左子树为空的情况
if(node.left == null){
Node rightNode = node.right;
node.right = null;
size --;
return rightNode;
}
// 待删除节点右子树为空的情况
if(node.right == null){
Node leftNode = node.left;
node.left = null;
size --;
return leftNode;
}
// 待删除节点左右子树均不为空的情况
// 找到比待删除节点大的最小节点, 即待删除节点右子树的最小节点
// 用这个节点顶替待删除节点的位置
Node successor = minimum(node.right);
successor.right = removeMin(node.right);
successor.left = node.left;
node.left = node.right = null;
return successor;
}
}