• 红黑树


    public class RedBlackBST<Key extends Comparable<Key>,value>
    {
        private Node root;
        private static final boolean RED = true;
        private static final boolean BLACK = false;
        private class Node
        {
            Key key;  
            Vlaue val;  //value是个啥?  似乎不需要。 我再看看 - -
            Node left,right,parent;
            boolean color;
    
            public Node(Key key, Vlaue val, Node parent,boolean color)
            {
                this.key = key;
                this.val = val;
                this.color = color;
            }
        }
            public Vlaue get(Key key)
            {
                Node x = root;
                while(x != null)
                {
                    int cmp = key.compareTo(x.key);
                    if(cmp < 0) x = x.left;
                    else if(cmp > 0) x = x.right;
                    else return x.val;
                }
                return null;
            }
    
            //插入节点
            public void put(Key key, Value value)
            {
                if(root == null) root = new Node(key, value, null, BLACK);
    
                //从根节点往下寻找合适的插入位置
                Node parent = null;   //查找位置,然后插入节点
                Node cur = root;
                //保持二叉树的特性,while循环寻找插入位置。插入位置肯定是null处
                while(cur != null)
                {
                    parent = cur;
                    if(key.compareTo(cur.key) > 0) cur = cur.right;
                    else cur = cur.left;
                }
    
                Node n = new Node(key, value, parent, RED);//普通的新建节点为红色
                //将新节点插入parent下
                if(key.compareTo(parent.key) > 0)parent.right = n;
                else parent.left = n;
    
                //插入新节点后要调整树中部分节点的颜色和属性来红黑树的特征不被破坏
                fixAfterInsertion(n);
    
            }
    
            private Node parentOf(Node x) {return x == null? null:x.parent;}
    
            private boolean colorOf(Node x){return x == null? null:x.color;}
        
            private Node leftOf(Node x){return x == null? null : x.left;}
    
            private Node rightOf(Node x){return x == null? null: x.right;}
    
            private void setColor(Node x, boolean color){if(x!=null) x.color = color;}
    
            //变色
            //不知道下面的case是怎么出来,应该是总结出来的
            private void fixAfterInsertion(Node x)
            {
                //父节点的颜色为红色
                while(x!=null && colorOf(parentOf(x)) == RED)
                {
                    //父节点的父节点
                    Node grandPa = parentOf(parentOf(x));
                    Node parent = parentOf(x);
    
                    //父节点是祖父节点的左孩子
                    if(parent == leftOf(grandPa)){
                        Node uncle = rightOf(grandPa);
                        //case1: 叔叔节点是红色
                        if(colorOf(uncle) == RED)
                        {
                            setColor(parent, BLACK);
                            setColor(uncle, BLACK);
                            setColor(grandPa, RED);
                            x = grandPa;  //这一步是为了之后的旋转
                        }else
                        {
                            //case2: 叔叔是黑色,且当前是右孩子
                            if(x == rightOf(parent))
                            {
                                x = parent;
                                rotateLeft(x);
                            }
    
                            //case3: 叔叔是黑色,且当前是左孩子
                            setColor(parent, BLACK);
                            setColor(grandPa, RED);
                            rotateRight(grandPa);
                        }
                    }
                    //父节点时祖父节点的右孩子
                    else
                    {
                        //case4: 叔叔节点时红色
                        Node uncle = leftOf(grandPa);
                        if(colorOf(uncle) ==  RED)
                        {
                            setColor(parent, BLACK);
                            setColor(uncle, BLACK);
                            setColor(grandPa, RED);
                            x= grandPa;
                                                }
                        //case5: 叔叔黑色,且当前是左孩子
                        else
                        {
                            if(x == leftOf(parent))
                            {
                                x = parent;
                                rotateRight(x)
                            }
                            //case6: 叔叔是黑色,且当前节点时右孩子
                            setColor(parent, BLACK);
                            setColor(grandPa,RED);
                            rotateLeft(grandPa);
                        }
                        
                    }
                }
                setColor(this.root, BLACK);
            }
            //左旋转, 右孩子升为根节点, 右孩子的左孩子左移
            //知道指针和链表这里就很好理解了
            public viod rotateLeft(Node x)
            {
                if(x == null) return;
                Node y = x.right;  //右孩子
                //建立旋转后的父子关系
                x.right = y.left;  //右孩子的左孩子变为变化后的x的右孩子
                if(y.left != null) y.left.parent = x;
                y.parent = x.parent;   //将x的parent赋值给y的parent .  
    
                if(x.parent == null) root = y;
                else if(x.parent.left == x) x.parent.left = y;
                else x.parent.right = y;
    
                y.left = x;  //将x设为y的左孩子
                x.parent = y; //将y设为x的parent
            }
    
            //右旋转  左孩子上升为根节点。左孩子的右孩子变为x的左孩子
            public void rotateRight(Node x)
            {
                if(x == null) rturn;
                Node y = x.left;
                x.left = y.right;
                if(y.right == null) y.right.parent = x;
                y.parent = x.parent;
    
                if(x.parent == null) root = y;
                else if(x.parent.left == x) x.parent.left = y;
                else x.parent.right = y;
    
                y.left = x;
                x.parent = y;
            }
        }
    }
  • 相关阅读:
    剑指offer:面试题25、二叉树中和为某值的路径
    剑指offer:面试题24、二叉搜索树的后续遍历序列
    剑指offer:面试题23、从上往下打印二叉树
    剑指offer:面试题22、栈的压入、弹出序列
    剑指offer:面试题21、包含min函数的栈
    剑指offer:面试题20、顺时针打印矩阵
    剑指offer:面试题19、二叉树的镜像
    剑指offer:面试题18、树的子结构
    剑指offer:面试题17、合并两个排序的链表
    剑指offer:面试题16、反转链表
  • 原文地址:https://www.cnblogs.com/GlazedCat/p/10549117.html
Copyright © 2020-2023  润新知