java实现二分检索树

二分检索树的左子树比根小,右子树比根大。这里用二分检索树实现了一个符号表,包括常用的api。

package symbolForm;

import simpleStructure.Queue;

public class BST<K extends Comparable<K>, V> implements SymbolForm<K, V>
{
    private Node root;

    private class Node
    {
        public K key;
        public V value;
        public int num; // 以该节点为根的树的节点总数
        public Node left, right;

        public Node(K key, V value, int N)
        {
            this.key = key;
            this.value = value;
            this.num = N;
        }

        public Node(Node n)
        {
            this.key = n.key;
            this.value = n.value;
            this.num = n.num;
            this.left = n.left;
            this.right = n.right;
        }
    }

    @Override
    public void put(K key, V value)
    {
        root = put(root, key, value);
    }

    private Node put(Node root, K key, V value)
    {
        if (root == null)
            return new Node(key, value, 1);
        int cmp = key.compareTo(root.key);
        if (cmp < 0)
            root.left = put(root.left, key, value);
        else if (cmp > 0)
            root.right = put(root.right, key, value);
        else
            root.value = value;
        root.num = size(root.left) + size(root.right) + 1;
        return root;
    }

    @Override
    public V get(K key)
    {
        // TODO Auto-generated method stub
        Node x = get(root, key);
        if(x == null) return null;
        return x.value;
    }

    private Node get(Node root, K key)
    {
        if (root == null)
            return null;
        int cmp = root.key.compareTo(key);
        if (cmp > 0)
            return get(root.left, key);
        if (cmp < 0)
            return get(root.right, key);
        return root;

    }

    @Override
    public boolean contain(K key)
    {
        // TODO Auto-generated method stub
        return get(key) != null;
    }

    @Override
    public boolean isEmpty()
    {
        // TODO Auto-generated method stub
        return size() == 0;
    }

    @Override
    public int size()
    {
        // TODO Auto-generated method stub
        return size(root);
    }

    private int size(Node n)
    {
        if (n == null)
            return 0;
        return n.num;
    }

    @Override
    public K min()
    {
        // TODO Auto-generated method stub
        if (root == null)
            return null;
        Node r = new Node(root);
        while (r.left != null)
        {
            r = r.left;
        }
        return r.key;
    }

    @Override
    public K max()
    {
        // TODO Auto-generated method stub
        if (root == null)
            return null;
        Node r = new Node(root);
        while (r.right != null)
        {
            r = r.right;
        }
        return r.key;
    }

    @Override
    public K floor(K key)
    {
        // TODO Auto-generated method stub
        Node x = floor(root, key);
        if (x == null)
            return null;
        return x.key;
    }

    /**
     * 逻辑:如果给定的键key小于二叉查找树的根节点的键, 那么小于等于key的最大键floor(key)一定在根节点的左子树中,
     * 如果给定的键key大于二叉查找数的根节点,那么只有当根节点右子树 中存在小于等于key的节点时,floor(key)才会出现在右子树中
     * 否则根节点就是floor(key)
     * 
     * @param n
     * @param key
     * @return
     */
    private Node floor(Node n, K key)
    {
        if (n == null)
            return null;
        int cmp = key.compareTo(n.key);
        if (cmp < 0)
            return floor(n.left, key);
        else if (cmp > 0)
        {
            Node t = floor(n.right, key);
            if (t == null)
                return n;
            else
                return t;
        } else
            return n;
    }

    @Override
    public K ceiling(K key)
    {
        // TODO Auto-generated method stub
        Node x = ceiling(root, key);
        if (x == null)
            return null;
        return x.key;
    }

    private Node ceiling(Node n, K key)
    {
        if (n == null)
            return null;
        int cmp = key.compareTo(n.key);
        if (cmp > 0)
            return ceiling(n.right, key);
        if (cmp == 0)
            return n;
        Node t = ceiling(n.left, key);
        if (t == null)
            return n;
        else
            return t;
    }

    @Override
    public int rank(K key)
    {
        // TODO Auto-generated method stub
        return rank(root, key);
    }

    private int rank(Node n, K key)
    {
        if (n == null)
            return 0;
        int cmp = key.compareTo(n.key);
        if (cmp == 0)
            return size(n.left);
        if (cmp < 0)
            return rank(n.left, key);
        return size(n.left) + 1 + rank(n.right, key);
    }

    @Override
    public K select(int k)
    {
        // TODO Auto-generated method stub
        Node x = select(root, k);
        return x.key;
    }

    private Node select(Node n, int k)
    {
        int t;
        if (n.left != null)
            t = n.left.num;
        else
            t = 0;
        if (t == k)
            return n;
        if (t > k)
            return select(n.left, k);
        return select(n.right, k - t - 1);
    }

    @Override
    public void deleteMin()
    {
        // TODO Auto-generated method stub
        root = deleteMin(root);
    }

    private Node deleteMin(Node n)
    {
        if (n.left == null)
            return n.right;
        n.left = deleteMin(n.left);
        n.num = size(n.left) + size(n.right) + 1;
        return n;
    }

    @Override
    public void deleteMax()
    {
        // TODO Auto-generated method stub
        root = deleteMax(root);
    }

    private Node deleteMax(Node n)
    {
        if (n.right == null)
            return n.left;
        n.right = deleteMax(n.right);
        n.num = size(n.left) + size(n.right) + 1;
        return n;
    }

    @Override
    public void delete(K key)
    {
        // TODO Auto-generated method stub
        root = delete(root, key);
    }

    private Node delete(Node n, K key)
    {
        if (n == null)
            return null;
        int cmp = key.compareTo(n.key);
        if (cmp < 0)
            n.left = delete(n.left, key);
        else if (cmp > 0)
            n.right = delete(n.right, key);
        else
        {
            Node t = n;
            n = min(t.right);
            if (n != null)
            {
                n.right = deleteMin(t);
                n.left = t.left;
            }
        }
        if (n != null)
            n.num = size(n.left) + size(n.right) + 1;
        return n;
    }

    /**
     * 心得,要写好一个递归,先准确理解当前函数的用途,含义. 因为要在当前函数中再使用这个函数
     * @param n
     * @return
     */
    private Node min(Node n)
    {
        if (n == null)
            return null;
        if (n.left == null)
            return n;
        return min(n.left);
    }

    @Override
    public int size(K lo, K hi)
    {
        // TODO Auto-generated method stub
        return size(root, lo, hi);
    }

    // 这是我写过的最牛叉的递归算法了
    private int size(Node n, K lo, K hi)
    {
        if (n == null)
            return 0;
        int sum = 0;
        int cmplo = lo.compareTo(n.key);
        int cmphi = hi.compareTo(n.key);
        if (cmplo < 0)
            sum += size(n.left, lo, hi);
        if (cmplo <= 0 && cmphi >= 0)
            sum += 1;
        if (cmphi >= 0)
            sum += size(n.right, lo, hi);
        return sum;
    }

    @Override
    public Iterable<K> keys()
    {
        // TODO Auto-generated method stub
        return keys(min(), max());
    }

    @Override
    public Iterable<K> keys(K lo, K hi)
    {
        // TODO Auto-generated method stub
        Queue<K> queue = new Queue<K>();
        keys(root, lo, hi, queue);
        return queue;
    }

    // 这是我目前见过最牛叉的递归算法了。。。
    private void keys(Node n, K lo, K hi, Queue<K> queue)
    {
        if (n == null)
            return;
        int cmp1 = lo.compareTo(n.key);
        int cmp2 = hi.compareTo(n.key);
        if (cmp1 < 0)
            keys(n.left, lo, hi, queue);
        if (cmp1 <= 0 && cmp2 >= 0)
            queue.enqueue(n.key);
        if (cmp2 > 0)
            keys(n.right, lo, hi, queue);
    }


}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
二分搜索(Binary Search Tree)是一种基于二分查找的数据结构,它的左子中的所有节点都小于根节点,右子中的所有节点都大于根节点。最优二分搜索(Optimal Binary Search Tree)也称为哈夫曼(Huffman Tree),是一种带权路径最短的二叉,它的带权路径长度最小,也就是说,它的各个叶子节点的深度加上其权值的乘积之和最小。 以下是用Java代码实现最优二分搜索的示例: ```java public class OptimalBST { private static final int INF = Integer.MAX_VALUE; private static int n; private static int[] p; private static int[] q; private static int[][] w; private static int[][] e; private static int[][] root; public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("请输入节点数:"); n = scanner.nextInt(); p = new int[n + 1]; q = new int[n + 1]; System.out.println("请输入节点的概率:"); for (int i = 1; i <= n; i++) { p[i] = scanner.nextInt(); } System.out.println("请输入虚拟节点的概率:"); for (int i = 0; i <= n; i++) { q[i] = scanner.nextInt(); } w = new int[n + 2][n + 2]; e = new int[n + 2][n + 2]; root = new int[n + 1][n + 1]; optimalBST(); System.out.println("最优二叉搜索的带权路径长度为:" + e[1][n]); } private static void optimalBST() { // 初始化 w、e、root 数组 for (int i = 1; i <= n + 1; i++) { w[i][i - 1] = q[i - 1]; e[i][i - 1] = q[i - 1]; } for (int len = 1; len <= n; len++) { for (int i = 1; i <= n - len + 1; i++) { int j = i + len - 1; e[i][j] = INF; w[i][j] = w[i][j - 1] + p[j] + q[j]; for (int k = i; k <= j; k++) { int t = e[i][k - 1] + e[k + 1][j] + w[i][j]; if (t < e[i][j]) { e[i][j] = t; root[i][j] = k; } } } } } } ``` 该代码中,使用了动态规划的思想,通过计算每个子的带权路径长度,逐步求得最优二叉搜索的带权路径长度。在计算过程中,使用了一个 root 数组,记录了每个子的根节点。最后,根据 root 数组和节点的概率,可以构建出最优二叉搜索

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值