红黑树

一、红黑树

       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;
       }
    }
}

 

posted @ 2020-03-29 15:31  撑起一片阳光  阅读(277)  评论(0编辑  收藏  举报