二分搜索树(JAVA)

二分搜索树是在二叉树的基础上定义:
所有节点的左子节点需要小于(不大于)该节点,右子节点需要大于(不小于)该节点
实现代码如下:
注意:这里实现的二分搜索树会去重,如果允许重复节点,则在添加元素时,定义值相等的元素存放在节点的左子节点或右子节点中。

public class BST<E extends Comparable<E>> {

    private class Node<E> {
        public E val;
        public Node<E> left, right;

        public Node(E e) {
            val = e;
            left = right = null;
        }
    }

    private Node<E> root;
    private int size;

    public BST() {
        root = null;
        size = 0;
    }

    public int size() {
        return size;
    }

    public boolean isEmpty() {
        return size == 0;
    }

    public void inOrder() {
        inOrder(root);
    }

    private void inOrder(Node<E> node) {
        if (node == null) {
            return;
        }

        inOrder(node.left);
        System.out.println(node.val);
        inOrder(node.right);
    }

    public void add(E e) {

        // version 1
        // if (root == null) {
        //     root = new Node<>(e);
        //     size++;
        // } else {
        //     addElementToTree(root, e);
        // }

        // version 2
        root = addElementToTreeAndReturnRoot(root, e);
    }

    /**
     * 将元素加入以指定节点为根的子树中
     * @param node 子树的根节点,调用前需要判空
     * @param e
     */
    private void addElementToTree(Node<E> node, E e) {
        int comp = e.compareTo(node.val);
        if (comp == 0) {
            return;
        }
        if (comp < 0) {
            // 需要放入左子树
            if (node.left == null) {
                // 左子树为空,新建左子树并完成创建
                node.left = new Node<>(e);
                size++;
                return;
            } else {
                // 左子树不为空,将元素添加在左子树上
                addElementToTree(node.left, e);
            }
        } else {
            // 需要放入右子树
            if (node.right == null) {
                // 右子树为空,新建右子树并完成创建
                node.right = new Node<>(e);
                size++;
                return;
            } else {
                // 左子树不为空,将元素添加在左子树上
                addElementToTree(node.right, e);
            }
        }
    }

    /**
     * 将元素加入以指定节点为根的子树,并返回该子树的根节点
     * @param node 子树的根节点
     * @param e    元素
     * @return
     */
    private Node<E> addElementToTreeAndReturnRoot(Node<E> node, E e) {
        if (node == null) {
            size++;
            return new Node<>(e);
        }

        int comp = e.compareTo(node.val);
        if (comp < 0) {
            // 放入左子树
            node.left = addElementToTreeAndReturnRoot(node.left, e);
        } else if (comp > 0) {
            // 放入右子树
            node.right = addElementToTreeAndReturnRoot(node.right, e);
        }

        return node;
    }

    public boolean contains(E e) {
        return contains(root, e);
    }

    /**
     * 在以指定节点为根节点的子树上搜索元素是否存在
     * @param node
     * @param e
     * @return
     */
    private boolean contains(Node<E> node, E e) {
        if (node == null) {
            return false;
        }

        int comp = e.compareTo(node.val);

        if (comp < 0) {
            return contains(node.left, e);
        }

        if (comp > 0) {
            return contains(node.right, e);
        }

        return true;
    }

    public E getMin() {
        if (isEmpty()) {
            throw new IllegalArgumentException("BST is empty!");
        }
        return getMin(root).val;
    }

    private Node<E> getMin(Node<E> node) {
        if (node.left == null) {
            return node;
        } else {
            return getMin(node.left);
        }
    }

    public E getMax() {
        if (isEmpty()) {
            throw new IllegalArgumentException("BST is empty!");
        }
        return getMax(root).val;
    }

    private Node<E> getMax(Node<E> node) {
        if (node.right == null) {
            return node;
        } else {
            return getMax(node.right);
        }
    }

    public E removeMin() {
        E ret = getMin();
        root = removeMin(root);
        return ret;
    }

    /**
     * 删除以指定节点为根的子树中的最小节点
     * @param node
     * @return 返回删除后的子树的根节点
     */
    private Node<E> removeMin(Node<E> node) {
        if (node.left == null) {
            // 如果子树没有左子树,删除node节点,返回node节点的右子树为删除后的子树
            Node<E> right = node.right;
            node.right = null;
            size--;
            return right;
        } else {
            // 如果子树有左子树,递归
            node.left = removeMin(node.left);
            return node;
        }
    }

    public E removeMax() {
        E ret = getMax();
        root = removeMax(root);
        return ret;
    }

    /**
     * 删除以指定节点为根的子树中的最大节点
     * @param node
     * @return 返回删除后的子树的根节点
     */
    private Node<E> removeMax(Node<E> node) {
        if (node.right == null) {
            // 如果子树没有右子树,删除node节点,返回node节点的左子树为删除后的子树
            Node<E> left = node.left;
            node.left = null;
            size--;
            return left;
        } else {
            // 如果子树有右子树,递归
            node.right = removeMax(node.right);
            return node;
        }
    }

    public void remove(E e) {
        root = remove(root, e);
    }

    private Node<E> remove(Node<E> node, E e) {
        if (node == null) {
            return null;
        }

        int comp = e.compareTo(node.val);
        if (comp < 0) {
            node.left = remove(node.left, e);
            return node;
        }

        if (comp > 0) {
            node.right = remove(node.right, e);
            return node;
        }

        if (node.left == null) {
            size--;
            return node.right;
        }

        if (node.right == null) {
            size--;
            return node.left;
        }

        // Node<E> successor = getMin(node.right);
        // node.right = removeMin(node.right);
        //
        // successor.left = node.left;
        // successor.right = node.right;

        Node<E> predecessor = getMax(node.left);
        node.left = removeMax(node.left);

        predecessor.left = node.left;
        predecessor.right = node.right;

        return predecessor;
    }

    /**
     * 比指定元素小的最大值(地板)
     * @param e
     * @return
     */
    public E floor(E e) {
        return floor(root, e).val;
    }

    /**
     * 比较子树根节点Node与指定元素e的大小
     * 如果 Node 更大
     * ----在Node的左子树中继续找
     * 如果 Node 更小
     * ----如果Node的右子树不存在
     * --------返回 Node
     * ----如果Node的右子树存在
     * --------搜索右子树的最小值
     * --------如果该最小值比 e 大,返回 Node
     * --------如果该最小值没有 e 大,在Node的右子树中继续找
     * 如果 相等
     * ----返回 Node
     * @param node
     * @param e
     * @return
     */
    private Node<E> floor(Node<E> node, E e) {
        if (node == null) {
            throw new IllegalArgumentException("no found!");
        }
        int comp = node.val.compareTo(e);

        if (comp > 0) {
            return floor(node.left, e);
        }

        if (comp < 0) {
            Node<E> right = node.right;
            if (right == null) {
                return node;
            } else {
                Node<E> min = getMin(right);
                if (min.val.compareTo(e) > 0) {
                    return node;
                } else {
                    return floor(right, e);
                }
            }
        }

        return node;
    }

    /**
     * 比指定元素大的最小值(天花板)
     * @param e
     * @return
     */
    public E ceil(E e) {
        return ceil(root, e).val;
    }

    /**
     * 比较子树根节点Node与指定元素e的大小
     * 如果 Node 更小
     * ----在Node的右子树中继续找
     * 如果 Node 更大
     * ----如果Node的左子树不存在
     * --------返回 Node
     * ----如果Node的左子树存在
     * --------搜索左子树的最大值
     * --------如果该最大值比 e 大,或相等,在Node的左子树中继续找
     * --------如果该最大值比 e 小,返回Node
     * 如果 相等
     * ----返回 Node
     * @param node
     * @param e
     * @return
     */
    private Node<E> ceil(Node<E> node, E e) {
        if (node == null) {
            throw new IllegalArgumentException("not found!");
        }
        int comp = node.val.compareTo(e);

        if (comp < 0) {
            return ceil(node.right, e);
        }

        if (comp > 0) {
            Node<E> left = node.left;
            if (left == null) {
                return node;
            } else {
                Node<E> max = getMax(left);
                if (max.val.compareTo(e) >= 0) {
                    return ceil(left, e);
                } else {
                    return node;
                }
            }
        }

        return node;
    }

    private static <E extends Comparable<E>> BST<E> fromArray(E... arr) {
        BST<E> bst = new BST<>();
        for (E e : arr) {
            bst.add(e);
        }
        return bst;
    }

    public static void main(String[] args) {
        /**
         *                     10
         *        .........         .........
         *   4                                  90
         *                                  ...
         *                              29
         *                        ...        ...
         *                    19                     55
         *                        ...         ....       ....
         *                            28   33                  76
         *                                    ...         ...
         *                                        48   75
         */
        BST<Integer> bst = fromArray(10, 4, 90, 29, 55, 33, 19, 76, 48, 75, 28);
        bst.inOrder();

        System.out.println(56 + " floor " + bst.floor(56));
        System.out.println(40 + " ceil " + bst.ceil(40));
    }

}

二分搜索树的一个性质:
中序遍历的结果是有序的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值