zoukankan      html  css  js  c++  java
  • 红黑树

    一、红黑树

           1.定义:红黑树时含有红黑节点并满足下列条件的二叉查找树

                   1)红色节点均为左节点

                   2)不能有两个连续的红节点

                   3)该树为完美黑色平衡的,即任意空连接到根节点的路径相同

          2.红黑树的平衡化

              1)左旋:当前节点的左子节点为黑色,右子节点为红色时。

                    *  左旋的过程:(1)让x节点的左子节点变为h的右子节点。

                                             (2)x的右子节点变为h

                                             (3)让h的color属性变为x的color属性

                                             (4)h节点变为红色

                                       

               2)右旋 :当某个节点的左子节点为红色,左子节点的左子节点也为红色,则需要右旋

                     右旋过程:(1)让x节点的右子节点做为h节点的左子节点

                                       (2)让h作为x的右子节点

                                       (3)让x的colcor变成h的colcor属性值

                                       (4)让h的color为Red        

                                    

              3)颜色反转

                     当一个节点的左子节点和右子节点都为红色,此时需要反转,只需把两个子节点变为黑色,而把父节点变为红色即可。

                    

                注意:在每次插入时的节点都为红色节点,根节点默认为黑色

    红黑树的设计:

               

    public class RedBlackTree<Key extends Comparable<Key>, Value> {
        //根节点
        private Node root;
        //个数
        private int N;
        //黑色节点
        private static final boolean RED=true;
        //红色节点
        private static final boolean BLACK=false;
    
        /**
         * 节点类
         */
        public class Node{
            //存储键
            public Key key;
            //存储值
            public Value value;
            //左子节点
            public Node left;
            //右子节点
            public Node right;
            //节点的颜色
            public boolean color;
    
            public Node(Key key, Value value, Node left, Node right, boolean color) {
                this.key = key;
                this.value = value;
                this.left = left;
                this.right = right;
                this.color = color;
            }
        }
    
        /**
         * 获取数中个数
         */
        public int size(){
            return N;
        }
    
        /**
         * 判断当前节点是否为红色
         */
        public boolean isRed(Node x){
            if (x==null){
                return false;
            }
            return x.color==RED;
        }
        /**
         * 左旋转
         */
        private Node rotateLeft(Node h){
            //获取h右子节点表示为x
            Node x=h.right;
            //将x左节点设为h的右节点
            h.right=x.left;
            //将x的左节点设为h
            x.left=h;
            //把x的color变为h的color属性
            x.color=h.color;
            //h变为红色
            h.color=RED;
            return x;
        }
        /**
         * 右旋
         */
        private Node rotateRight(Node h){
            //获取h的左子节点设为x
            Node x =h.left;
            //让x的右子节点变为h的左子节点
            h.left=x.right;
            //让h做为x的右子节点
            x.right=h;
            //让x的color等于h的color属性
            x.color=h.color;
            //让h的color为红色
            h.color=RED;
            return x;
        }
        /**
         * 颜色反转
         */
        private void flipColors(Node h){
            //让父节点变为红色
            h.color=RED;
            //让左右子节点都变为黑色
            h.left.color=BLACK;
            h.right.color=BLACK;
        }
        /**
         * 在整个树上完成插入操作
         */
        public void put(Key key,Value value){
           root= put(root,key,value);
            //让根节点的颜色总是黑色
            root.color=BLACK;
        }
        /**
         * 在指定数中插入操作,并返回添加元素新树
         */
        private Node put(Node h,Key key,Value value){
           //判断h是否为空,为空返回一个红色节点
            if (h==null){
                N++;
                return new Node(key,value,null,null,RED);
            }
            //不为空时,判断h节点的key值和key的大小
            int cmp = key.compareTo(h.key);
            if (cmp>0){
                //继续往右
                h.right=put(h.right,key,value);
            }else if (cmp<0){
                //继续往左
                h.left=put(h.left,key,value);
            }else {
                //替换
                h.value=value;
            }
            //进行左旋,h的左子节点为黑色,右子节点为红色
            if (isRed(h.right) && !isRed(h.left)){
                   h=rotateLeft(h);
            }
            //进行右旋,h的左子节点和左子节点的左子节点都为红色
            if (isRed(h.left) && isRed(h.left.left)){
                h=rotateRight(h);
            }
            //颜色反转,h的左右子节点都为红色
            if (isRed(h.left) && isRed(h.right)){
                flipColors(h);
            }
            return h;
        }
        //根据key,从树中找到值
        public Value get(Key key){
    
            return get(root,key);
        }
    
        //从指定的树中,查找key作对应的值
        public Value get (Node x,Key key){
           if (x == null){
               return null;
           }
            int cmp = key.compareTo(x.key);
           if (cmp>0){
               return get(x.right,key);
           }else if (cmp<0){
               return get(x.left,key);
           }else {
               return x.value;
           }
        }
    }
  • 相关阅读:
    SSH 免密登录配置
    Hadoop 2.7.2 集群安装配置
    将oracle数据库中数据写入excel文件
    PLSQL提交请求集
    oracle会计工作总结,EBS 创建会计科目 小结
    将oracle数据库中数据写入excel文件
    如何成为一名优秀的工程师(听讲座有感) Winema
    基于W5300的嵌入式以太网接口设计 Winema
    Java 基础入门随笔(2) JavaSE版——关键字、进制转换、类型转换
    VMware 11安装Mac OS X 10.10 及安装Mac Vmware Tools.
  • 原文地址:https://www.cnblogs.com/cqyp/p/12592556.html
Copyright © 2011-2022 走看看