二叉查找树

来源:互联网 发布:spd7网络信号避雷器 编辑:程序博客网 时间:2024/05/16 04:01

首先我们来理清一个概念,在二叉树中,每个节点只能有一个父节点(根据根据点例外,它没有父节点),而且每个节点都是由左右两个链接,分别指向自己的左子节点和右子节点,我们可以将这样的链接看成一个二叉树

 

二叉树查找:在每次经过一次运算后,所需要的查找的数量就减少一般。随着我们不断的向下查找,当前节点所表示的子树大小也在减少(理想状态是减少一半)。当找到一个含有被查找到的键的节点(命中)或者当前子树变成空(未命中)是这个过程才会结束。

代码实现:

package com.test;import java.util.Queue;public class BST<Key extends Comparable<Key>,Value>{    /*     * 二叉树的符号表     *    这段代码用二叉查找树实现了有序符号表的API,树有Node对象组成,     *    每个对象都含有一对键值、两天链接和一个结点计数器N。     *    每个Node对象都是一个含有N个结点的子树的根结点     *    它的左链接指向一颗小于这个结点的所有键组成的二叉树     *    它的右结点指向一个大于这个结点的所有键促成的二叉树。     *    root变量指向二叉树的根结点Node对象(这课树包含了符号表中的多有键值对)     */    private Node root;        //二叉查找数组的根据点        public class Node {        private Key key;            //键        private Value val;        //值        private Node left, right;        //指向子树的链接        private int N;            //以该节点为根的子树中的节点总数        public Node(Key key2, Value val2, int i) {            // TODO Auto-generated constructor stub        }    public void Node(Key key,Value val,int N) {        this.key = key;        this.val = val;        this.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){        //在以x为根据点的子树中查找并返回key所对应的值        //如果找不到则返回null        if (x == null)             return null;        int cmp = key.compareTo(x.key);        if (cmp < 0)             return get(x.left,key);        if (cmp >0)            return get(x.right.key);        else            return x.val;    }    public void put (Key key , Value val) {        //查找key,找到则更新它的值,否则为它创建一个新的结点        root = put(root , key , val);    }    private Node put (Node x , Key key , Value val){        //如果key存在于里x为根据点的自主中则更新它的值        //否则将以key和val为键值对的新节点插入到该子树中        if (x == null)            return new Node(key , val ,1);        int cmp = key.compareTo(x.key);        if (cmp < 0)            x.left = put(x.left,key,val);        if(cmp > 0)            x.right = put(x.right,key,val);        else            x.val = val;        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 min(root).key;    }    private Node max(Node x){        if (x.right == null)             return x;        return min(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 ceiling(Key key) {        Node x = ceiling(root , key);        if (x == null)             return null;        return x.key;    }    private Node ceiling(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;    }    /*     * 排名(rank)和挑选(select)     * rank():     * 假设我们想找到排名为k的键(即树中正好有k个小于它的键).     * 如果左子树的检点数t大于k,那么我们就继续(递归)在左子树中查找排名;     * 如果t等于k,我们就返回根结点中的键;     * 如果t小于k,我们就(递归)在右子树中朝赵排名为(k-t-1)的键.     */    public Key select(int k){        return select(root, k).key;    }    private Node select(Node x, int k) {        //返回排名为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;    }    /*     * rank()     */    public int rank(Key key){        return rank(key , root);    }    private int rank(Key key,Node x) {        //返回以x为根据点的自述中小于x.key的键的数量        if (x == null)             return 0;        int cmp = key.compareTo(x.key);        if (cmp < 0)             return rank(key , x.left);        else if(cmp > 0)            return 1 + size(x.left) + rank(key ,x.right);        else             return size(x.left);    }    /**     * 删除最大键和最小键     * 二叉查找树中最难实现的一个方法就是删除键delete(),     * 从符号表中删除一个键值对     *    下面是算法实现     */    public void deleteMin() {        root = deleteMin(root);    }    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;    }    /**     * 范围查找     * 要实现能够返回给定范围内键的keys()方法     * 我们首先需要一个遍历二叉查找树中的的基本方法     * 叫做中序遍历     */    public Iterable<Key> keys() {        return keys(min() ,max());    }    public Iterable<Key> keys(Key lo , Key hi){        Queue<Key> queue = new Queue<Key>();        keys(root, queue, lo, hi);        return queue;        }    private void keys(Node x, Queue<Key> queue,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,queue,lo,hi);        if(cmplo <= 0 && cmphi >= 0)            queue.enqueue(x.key);        if (cmphi > 0)            keys(x.right, queue, lo, hi);    }}}



原创粉丝点击