二分搜索树8-删除二分搜索树的最大元素和最小元素
我们来看一下二分搜索树最后一个重要的操作,也就是删除一个节点。对二分搜索树而言,删除一个节点相对是比较复杂的。我们将这个任务进行一下简单的拆解,我们在这一小节先来解决一个相对简单一些的删除,就是删除二分搜索数中的最小值和最大值。有些同学一眼还看不出来删除这个二分搜索树中的最小值和最大值和删除任意元素有什么关系,不过在下一小节就会看到,删除二分搜索数任意元素是可以复用这个逻辑的。
我们要想删除二分搜索树的最小值和最大值,就需要先找到二分搜索树的最小值和最大值,那么事实上,找到二分搜索树中的最小值和最大值是非常容易的。因为二分子的书的特点,他的左子树一定比这个节点要小。所以说二分搜索树的最小值一定是左子树一直往下走,一直走到底。同样的在二分搜索树中,右子树节点值,一定比当前节点要大,所以说右子树一直往下走,就一定是最大值。
注意向左走一直到走不动并不是一定要达到叶子节点,只用达到走不动为止,看下图的例子
向左走到16就走不动了,但是16下面还有元素
下面实现找到二分搜索树的最小节点的代码
// 寻找二分搜索树的最小元素
public E minimum(){
if(size == 0){//如果为空
throw new IllegalArgumentException("BST is empty");
}
Node minNode = minimum(root);
return minNode.e;
}
// 返回以node为根的二分搜索树的最小值所在的节点
private Node minimum(Node node){
//递归的终止条件,如果想下走为空,那么就终止了
if( node.left == null ){
return node;
}
//返回相应的节点的左子树的最小值
return minimum(node.left);
}
查找二分搜索树的最大元素的代码
// 寻找二分搜索树的最大元素
public E maximum(){
if(size == 0){
throw new IllegalArgumentException("BST is empty");
}
return maximum(root).e;
}
// 返回以node为根的二分搜索树的最大值所在的节点
private Node maximum(Node node){
if( node.right == null ){
return node;
}
return maximum(node.right);
}
删除最小值的思路:
- 如果要删除的节点是叶子节点,那么直接删除
- 如果要删除的节点下面有右子树,那么只用将其下的右子树整体上移成为上一个节点的左子树即可
上面删除22这个节点,然后把33及其以下的子树都变成44的左子树即可
同理可用在删除最大值上
下面删除最小值的代码实现
// 从二分搜索树中删除最小值所在节点, 返回最小值
public E removeMin(){
E ret = minimum();
root = removeMin(root);//注意这里,我们从root为根的树中删除掉了最小值,返回删除后的树的根节点,这个
//根节点就是新的root
return ret;
}
// 删除掉以node为根的二分搜索树中的最小节点
// 返回删除节点后新的二分搜索树的根
private Node removeMin(Node node){
// 递归的终止条件,当前节点没有左子树了,那么就是最小节点了
// 如果是最小节点,我们要做的是删除当前节点,但是当前节点很可能是有右子树的
// 我们先把该节点的右子树节点保存,然后就删除掉该右子树节点,最后把右子树节点返回即可
if(node.left == null){
Node rightNode = node.right;
node.right = null;//左节点为空了,让右子树也为空,相当于脱离了树
size --;
return rightNode;//返回右子树是为了后面的绑定操作
}
// 没有递归到底的情况,那么就递归调用其左子树,这个调用的过程会返回被删除节点的右子树,
//将返回的右子树重新绑定到上一层的node的左节点上就相当于彻底删除了那个元素
node.left = removeMin(node.left);
return node; // 删除后,根节点依然是node,返回即可
}
删除最大元素的代码如下
// 从二分搜索树中删除最大值所在节点
public E removeMax(){
E ret = maximum();
root = removeMax(root);
return ret;
}
// 删除掉以node为根的二分搜索树中的最大节点
// 返回删除节点后新的二分搜索树的根
private Node removeMax(Node node){
if(node.right == null){
Node leftNode = node.left;
node.left = null;
size --;
return leftNode;
}
node.right = removeMax(node.right);
return node;
}