二分搜索树 11 删除任意元素

在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;
    }

}

你可能感兴趣的:(二分搜索树 11 删除任意元素)