栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java实现 二叉查找树BST(递归版)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java实现 二叉查找树BST(递归版)

二叉查找树 BST (递归版)

参考 算法(第四版)

重点

    每个节点的键都大于其左子树中任意节点的键而小于其右子树中任意节点的键。

    对于二叉树中任意节点x总是有:

    size(x) = size(x.left) + size(x.right) + 1;

    (下文)root私有化,所以通过调用公共方法间接调用私有方法。

模板
public class BST, Value> {
    private Node root;

    private class Node{
        private Key key; // 键
        private Value val; // 值
        private Node left, right;
        private int N; // 节点数

        public Node(Key key, Value val, int n) {
            this.key = key;
            this.val = val;
            N = n;
        }
    }
}
(子)树总节点数
public int size(){
        return size(root);
    }

    private int size(Node x){
        if (x == null) return 0;
        else return x.N;
    }
查找
public Value get(Key key){ // 查找(每次都定义了树的一条路径)
        return get(root, key);
    }

    private Value get(Node x, Key key){
        if (x == null) return null;

        int cmp = key.compareTo(x.key); // 比较值
        if (cmp < 0) return get(x.left, key);
        else if (cmp > 0) return get(x.right, key);
        else return x.val;
    }
插入
public void put(Key key, Value val){ // 插入
        root = put(root, key ,val);
    }

    private Node put(Node x, Key key, Value val){
        if (x == null) return new Node(key, val ,1); // new

        int cmp = key.compareTo(x.key);
        if (cmp < 0) x.left = put(x.left, key, val); // insert
        else if (cmp > 0) x.right = put(x.right, key, val);
        else x.val = val; // update
        x.N = size(x.left) + size(x.right) + 1;
        return x;
    }
键的最值
public Key min(){ // 左下角最小键值
        return min(root).key;
    }

    private Node min(Node x){
        if (x.left == null) return x;
        return min(x.left);
    }

    public Key max(){ // 右下角最大键值
        return max(root).key;
    }

    private Node max(Node x){
        if (x.right == null) return x;
        return max(x.right);
    }
键的邻值
public Key floor(Key key){
        Node x =floor(root, key); // 找到对应节点
        if (x == null) return null;
        return x.key;
    }

    private Node floor(Node x, Key key){ // 含 地板键(升序最近) 的节点
        if (x == null) return null;

        int cmp = key.compareTo(x.key);
        if (cmp == 0) return x;
        if (cmp < 0) return floor(x.left, key); // 左子树找
        Node t = floor(x.right, key); // 右子树找
        if (t != null) return t;
        else return x;

    }

    public Key ceil(Key key){
        Node x =ceil(root, key); // 找到对应节点
        if (x == null) return null;
        return x.key;
    }

    private Node ceil(Node x, Key key){ // 含 天花板键(降序最近) 的节点
        if (x == null) return null;

        int cmp = key.compareTo(x.key);
        if (cmp == 0) return x;
        if (cmp > 0) return floor(x.right, key); // 右子树找
        Node t = floor(x.left, key); // 左子树找
        if (t != null) return t;
        else return x;
    }
(键的)排名 <–> 键值
public Key select(int k){ // 排名 -> 键值
        return select(root, k).key;
    }

    private Node select(Node x, int k){
        if (x == null) return null;

        int t = size(x.left);
        if (t > k) return select(x.left, k);
        else if (t < k) return select(x.right, k - t - 1);
        else return x;
    }

    public int rank(Key key){ // 键值 -> 排名
        return rank(key, root);
    }

    private int rank(Key key, Node x){
        if (x == null) return 0;

        int cmp = key.compareTo(x.key);
        if (cmp < 0) return rank(key, x.left);
        else if (cmp > 0) return size(x.left) + 1 + size(x.right);
        else return size(x.left);
    }

利用好size()

删除节点
public void deleteMin(){
        root = deleteMin(root); // 替换根节点,并更新该子树(其所有节点的键值都大于 x.key )
    }

    private Node deleteMin(Node x){
        if (x.left == null) return x.right; // 该根节点最小

        x.left = deleteMin(x.left);  // 自下而上更新 链接,节点计数器
        x.N = size(x.left) + size(x.right) + 1;
        return x;
    }

    public void delete(Key key){
        root = delete(root, key); // 更新被删除节点的位置
    }

    private Node delete(Node x, Key key){
        if (x == null) return null;

        int cmp = key.compareTo(x.key);
        if (cmp < 0) x.left = delete(x.left, key);
        else if (cmp > 0) x.right = delete(x.right, key);
        else {
            if (x.right == null) return x.left;
            if (x.left == null) return x.right;

            Node t = x; // 左右子树都不为空
            x = min(t.right); // 后继节点(其右子树中键值最小的节点)
            x.right = deleteMin(t.right);
            x.left = t.left;
        }

        x.N = size(x.left) + size(x.right) + 1; // 更新节点计数器
        return x;
    }

遍历
public void print(){
        print(root);
    }

    private void print(Node x){ // middle
        if (x == null) return;
        print(x.left);
        System.out.println(x.key);
        print(x.right);
    }

    public Iterable keys(){ // BST范围查找
        return keys(min(), max());
    }

    public Iterable keys(Key lo, Key hi){
        ArrayList list = new ArrayList<>();
        keys(root, list, lo, hi);
        return list;
    }

    private void keys(Node x, ArrayList list, Key lo, Key hi) {
        if (x == null) return;

        int cmplo = lo.compareTo(x.key); // 类比 二分查找 + 中序遍历
        int cmphi = hi.compareTo(x.key);
        if (cmplo < 0) keys(x.left, list, lo, hi);
        if (cmplo <= 0 && cmphi >= 0) list.add(x.key); // 加入list
        if (cmphi > 0) keys(x.right, list, lo, hi);
    }

keys()的返回数据类型支持foreach迭代即可。

测试
public static void main(String[] args) {
        BST bst = new BST<>();
        bst.put("D",4);
        bst.put("E",5);
        bst.put("F",6);
        bst.put("G",7);
        bst.put("A",1);
        bst.put("B",2);
        bst.put("C",3);


        Iterable k = bst.keys();

        for (String s : k) {
            System.out.println(s + " -> "+ bst.get(s));
        }


    }  

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/782362.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号