二分搜索树篇(3)—— 删除二分搜索树的最大元素和最小元素,任意值

版权声明:本文为博主原创文章,未经博主允许不得转载。 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
    在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/u012292754/article/details/86747984