版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012292754/article/details/86747984
1 删除二分搜索树的最大元素和最小元素
1.1 寻找最小节点
public E minimum() {
if (size == 0) {
throw new IllegalArgumentException("BST is empty");
}
return minimum(root).e;
}
//返回以 node 为根的二分搜索树的最小值的节点
private Node minimum(Node node) {
if (node.left == null) {
return node;
}
return minimum(node.left);
}
1.2 寻找最大节点
public E maximum() {
if (size == 0) {
throw new IllegalArgumentException("BST is empty");
}
return maximum(root).e;
}
private Node maximum(Node node) {
if (node.right == null) {
return node;
}
return maximum(node.right);
}
1.3 删除二分搜索树的最小节点
- 逻辑和 add 方法很像;
BST.java
public E removeMin() {
E ret = minimum();
root = removeMin(root);
return ret;
}
/*
* 删除以 node 为根的二分搜索树的最小节点
* 返回删除节点后新的二分搜索树的根
*
* */
private Node removeMin(Node node) {
if (node.left == null) {
Node rightNode = node.right;
node.right = null;
size--;
return rightNode;
}
node.left = removeMin(node.left);
return node;
}
1.4 删除二分搜索树的最大节点
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;
}
1.5 测试删除最小值
Main.java
package tree;
import java.util.ArrayList;
import java.util.Random;
public class Main {
public static void main(String[] args) {
BST<Integer> bst = new BST<>();
Random random = new Random();
int n = 1000;
for (int i = 0; i < n; i++) {
bst.add(random.nextInt(10000));
}
ArrayList<Integer> nums = new ArrayList<>();
while (!bst.isEmpty()) {
nums.add(bst.removeMin());
}
System.out.println(nums);
for (int i = 1; i < nums.size(); i++) {
if(nums.get(i-1) > nums.get(i)){
throw new IllegalArgumentException("Error");
}
}
System.out.println("removeMin complete");
}
}
2 删除二分搜索树的任意值
2.1 思路一(用右子树的最小节点代替)
- 删除左右都有孩子的节点 d,找到 s = min (d -> right),即节点59
- s 是 d 的后继
- s -> right = delMin(d -> right)
- s->left = d->left
public void remove(E e) {
root = remove(root, 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);
}
if (e.compareTo(node.e) > 0) {
node.right = remove(node.right, e);
} else { // e == node.e
// 待删除节点左子树为空
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;
}
return null;
}
2.2 思路2 (用左子树的最大节点代替)
3 二分搜索树的其他题目
3.1 floor 和 ceil
- 寻找 45 的 floor 和 ceil
3.2 rank 和 select
- 寻找排名第几的元素;
- 思路: 维护 size 的二分搜索树
3.3 维护 depth 的二分搜索树
3.4 支持重复元素的二分搜索树
- 思路1: 左子树节点 小于等于 根节点;
- 思路2 : Node 中添加一个作用域 count