有序符号表(二叉树实现,JAVA,算法(四))

来源:互联网 发布:宿迁12345网络问政电话 编辑:程序博客网 时间:2024/05/29 04:22

二叉树的实现和链表的节点是一致的,一个节点里面包含了键值对。只是由于二叉树的特性,便于插入,删除,查询等操作。二叉树的性质使这些操作都可以在logN的时间完成。但是,,,由于执行插入操作的不确定性,比如大多的升序或者降序插入,将导致二叉树的高度像链表一样,不再具有二叉树特有的logN的高度了。所以基于二叉树之上,一种可以维持自身高度的树出现了,那就是红黑树。下一篇再介绍红黑树。

package com.lizi.datastructure.symboltable;import java.util.ArrayList;import java.util.List;//二叉搜索树,继承的类在上一篇中有写到public class BinarySearchTreeST<Key extends Comparable<Key>,Value> extends SymbolTable<Key,Value> {    private Node root;//根节点    private class Node{        private Key key;  //键        private Value value;    //值        private Node left;      //左孩子        private Node right;     //右孩子        private int size;       //以该节点为根的子树中节点总数        public Node(Key key,Value value,int size){            this.key=key;            this.value=value;            this.size=size;        }    }    @Override    public void put(Key key, Value value) {        if(value==null) {delete(key); return;}        root=put(root, key, value);    }    private Node put(Node root,Key key,Value 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.size=size(root.left)+size(root.right)+1;        return root;    }    @Override    public Value get(Key key) {        return get(root, key);    }    private Value get(Node root,Key key) {        if(root==null)  return null;        int cmp=key.compareTo(root.key);        if(cmp<0)       return get(root.left, key);        else if(cmp>0)  return get(root.right, key);        else            return root.value;    }    @Override    public Value delete(Key key) {        Value value=get(key);        root=delete(root, key);        return value;    }    private Node delete(Node root,Key key) {        if(root==null) return null;        int cmp=key.compareTo(root.key);        if  (cmp<0) root.left=delete(root.left, key);        else if(cmp>0) root.right=delete(root.right, key);        else{//删除操作            if(root.right==null) return root.left;//左右孩子不全,直接替补上去            if(root.left==null) return root.right;            Node node=root;//包含左右孩子的删除操作            root=min(node.right);            root.right=deleteMin(node.right);            root.left=node.left;        }        root.size=size(root.left)+size(root.right)+1;        return root;    }    @Override    public int size() {        return size(root);    }    private int size(Node root) {        if (root==null) return 0;        else return root.size;    }    @Override    public Key min() {        return min(root).key;    }    private Node min(Node root) {        if(root.left==null) return root;        else return root.left;    }    @Override    public Key max() {        return max(root).key;    }    private Node max(Node root) {        if(root.right==null) return root;        else return root.right;    }    @Override    public Key floor(Key key) {        Node node=floor(root, key);        if(node==null) return null;        return node.key;    }    //找到第一个小于等于key的节点,再在它的右子树的左子树中找寻是否有小于key的节点    //如果有,那么这个键就是最接近key的节点,一个闪电形状    private Node floor(Node root,Key key) {        if(root==null) return null;        int cmp=key.compareTo(root.key);        if(cmp==0)      return root;        if(cmp<0)       return floor(root.left, key);        Node node=floor(root.right, key);        if (node!=null) return node;        else            return root;    }    @Override    public Key ceiling(Key key) {        Node node=ceiling(root, key);        if(node==null) return null;        return node.key;    }    private Node ceiling(Node root,Key key) {        if(root==null) return null;        int cmp=key.compareTo(root.key);        if(cmp==0)          return root;        if(cmp>0)           return floor(root.right, key);        Node node=floor(root.left, key);        if (node!=null)     return node;        else                return root;    }    @Override    public int rank(Key key) {        return rank(root, key);    }    //返回以root为根节点的子树中小于key的键的数量    private int rank(Node root,Key key) {        if(root==null) return 0;        int cmp=key.compareTo(root.key);        if(cmp<0)       return rank(root.left, key);        else if(cmp>0)  return rank(root.right, key)+size(root.left)+1;        else            return size(root.left);    }    @Override    public Key select(int index) {        if(index>=size()) return null;        return select(root,index).key;    }    //返回下标为index的键    private Node select(Node root,int index) {        if(root==null) return null;        int size=size(root.left);        if(size>index)      return select(root.left, index);        else if(size<index) return select(root.right, index);        else                return root;    }    //将下标位于low-high之间的所有键放入链表中    @Override    public Iterable<Key> keys(Key low, Key high) {        List<Key> list=new ArrayList<Key>();        keys(root,list,low,high);        return list;    }    private void keys(Node root,List<Key> list,Key low, Key high) {        if(root==null) return;        int cmplow=low.compareTo(root.key);        int cmphigh=high.compareTo(root.key);        if(cmplow<0) keys(root.left, list, low, high);        if(cmphigh<=0&&cmphigh>=0) list.add(root.key);        if(cmphigh>0) keys(root.right, list, low, high);    }    //删除最小的键    public void deleteMin(){        root=deleteMin(root);    }    private Node deleteMin(Node root){        if(root.left==null) return root.right;        root.left=deleteMin(root.left);//如果最小节点有右孩子,那么替代自身成为其父节点的左孩子        root.size=size(root.left)+size(root.right)+1;//左右孩子加上自身        return root;    }    //删除最大的键    public void deleteMax(){        deleteMax(root);    }    private Node deleteMax(Node root){        if(root.right==null) return root.left;        root.right=deleteMin(root.right);//如果最小节点有左孩子,那么替代自身成为其父节点的右孩子        root.size=size(root.left)+size(root.right)+1;//左右孩子加上自身        return root;    }    public void print() {        print(root);    }    private void print(Node root) {        if(root==null) return;        print(root.left);        System.out.println(" 键:"+root.key+" 值:"+root.value);        print(root.right);    }}
阅读全文
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 家里养的竹子的叶子发黄怎么办 发财树叶子发黄发黑怎么办打蔫 装修公司把衣柜型号弄错了怎么办 隔水炖锅里的陶瓷坏了怎么办? 色选大米带出比大怎么办? 做手足印如果漆刷到外面了怎么办 小区房子整租给民工影响邻居怎么办 种植牙植体中间的螺丝滑丝怎么办 宝宝1岁了牙齿表面脱落了怎么办 1岁3个月宝宝牙齿发黑脱落怎么办 种植牙中央螺栓断在牙根里怎么办 欧联杯冠军已经获得欧冠资格怎么办 孩子该上学了学校不收怎么办 帮室友带东西她忘给钱怎么办? 鸿合录播系统不会自动跟踪了怎么办 小米2s锁屏密码忘了怎么办 想用中国驾照去美国开车怎么办? 5座的车坐7个人怎么办 海尔电视机的设置调乱了怎么办 老公弟兄两个有个偏心的婆婆怎么办 农商银行u盾密码忘了怎么办 不熟的表弟表妹向你借钱怎么办 开货车撞到人家房子了怎么办 坐骨被摔跤后好多年没好怎么办 自动挡汽车电子手刹刹车失灵怎么办 买家拍了不包邮的宝贝付款了怎么办 包邮快递买家不要了运费怎么办 舞蹈劈叉练出肌肉劈不下去怎么办 腰间盘突出压迫神经腿疼怎么办盘 绑定了我身份证的微信被盗了怎么办 用身份证办的手机卡不用了怎么办 平安陆金所交易密码忘了怎么办 陆金所密码交易密码忘记怎么办 带介指手指月肿了拿不下来怎么办 老公搞建筑的要长期在外地怎么办 媳妇跟婆婆吵架老公帮婆婆该怎么办 在家里礼佛香炉剩下的香头怎么办 精索曲张最近一打篮球就蛋疼怎么办 都两天了快递还是显示已发货怎么办 中通快递到达一天就是不派送怎么办 顺丰派送员把快递寄错了怎么办