把握下面的这个最基本且简单的性质:
最小值:从根节点开始,不停地沿着左边节点的方向找,直到再也没有左节点为止;
最大值:从根节点开始,不停地沿着右边节点的方向找,直到再也没有右节点为止。
试着用非递归的方式实现一下。
下面的逻辑,虽然简单,但是有陷阱,自己要关注一下细节。
删除最小值的节点
关键把握一点:
如果最小值的节点没有右孩子,很好办,直接删除,如果最小值的节点有右孩子,让右孩子代替自己(自己试着在图上画出这个过程,就很好理解了)。
/**
* 从二分搜索树中删除最小 key 所在的节点
*/
public void removeMin() {
if (root != null) {
root = removeMin(root);
}
}
/**
* 删除以 node 为根的二分搜索树中的最小的节点
* 返回删除节点后新的二分搜索树的根
* @param node
* @return
*/
private Node removeMin(Node node) {
if (node.left == null) {
// 就是删除这个节点 node
Node rightNode = node.right;
node.right = null;
count--;
return rightNode;
}
node.left = removeMin(node.left);
return node;
}
代码:node.left = removeMin(node.left);
是很重要的(这里可以画一张图辅助我们理解)。
删除最大值的节点
/**
* 使用递归的方式删除二分搜索树最大 key 所在的节点
*/
public void removeMax() {
if (root != null) {
root = removeMax(root);
}
}
/**
* 删除以 node 为根的二分搜索树的 key 最大的那个节点
* 返回删除了节点以后的新的二分搜索树的根
*
* @param node
* @return
*/
public Node removeMax(Node node) {
if (node.right == null) {
Node leftNode = node.left;
node.left = null;
count--;
// 返回删除了节点以后的新的二分搜索树的根
return leftNode;
} else { // node.right != null
node.right = removeMax(node.right);
return node.right;
}
}
说明:
1、以上两个方法还可以使用循环的方式实现,可以尝试一下
2、以上的这两个删除的方法为我们删除任意一个节点做好的铺垫,请引起重视。