【源码解析】HashMap源码跟进(红黑树的实现)

HashMap中红黑树的定义和它内部的方法

     static final class TreeNode<K,V> extends LinkedHashMap.Entry<K,V> {
            TreeNode<K,V> parent;  //父亲节点 red-black tree links
            TreeNode<K,V> left;//左子树
            TreeNode<K,V> right;//右子树
            TreeNode<K,V> prev;    // needed, to unlink next upon deletion删除的时候使用
            boolean red;//标记颜色,默认红色
            TreeNode(int hash, K key, V val, Node<K,V> next) {
                super(hash, key, val, next);
            }
            final TreeNode<K,V> root(){//返回节点的根节点
            ...
            }
            static <K,V> void moveRootToFront(Node<K,V>[] tab, TreeNode<K,V> root){
                ... //把给定节点设为桶中的第一个元素
            }
            final TreeNode<K,V> find(int h, Object k, Class<?> kc){
                ... //从当前结点this开始通过给定的hash和key查找结点
            }
            final TreeNode<K,V> getTreeNode(int h, Object k) {
            ... // 从根节点开始寻找节点
            }
             static int tieBreakOrder(Object a, Object b) {
             ...//用来排序
             }
             final void treeify(Node<K,V>[] tab){
                 ...//链表树化
             }
             final Node<K,V> untreeify(HashMap<K,V> map){
                 ...//转化回链表
             }
             final TreeNode<K,V> putTreeVal(HashMap<K,V> map, Node<K,V>[] tab,
                                           int h, K k, V v){
                                               ...//放入树节点
                                           }
            
            final void removeTreeNode(HashMap<K,V> map, Node<K,V>[] tab,
                                      boolean movable) {
                ...//删除节点
                                      }
            final void split(HashMap<K,V> map, Node<K,V>[] tab, int index, int bit){
                ...//Resize()调用
            }
            static <K,V> TreeNode<K,V> rotateLeft(TreeNode<K,V> root,
                                                  TreeNode<K,V> p){
                ...//左旋                                                  }
            static <K,V> TreeNode<K,V> rotateRight(TreeNode<K,V> root, TreeNode<K,V> p){
                ...//右旋
                }
            static <K,V> TreeNode<K,V> balanceInsertion(TreeNode<K,V> root,TreeNode<K,V> x) {
                ...//插入后保持平衡
            }
            static <K,V> TreeNode<K,V> balanceDeletion(TreeNode<K,V> root,TreeNode<K,V> x) {
                ...//删除后保持平衡
            }
             static <K,V> boolean checkInvariants(TreeNode<K,V> t) {}
            

转化为红黑树–treeifyBin 方法

在HashMap中put方法时候,但数组中某个位置的链表长度大于8时,会调用treeifyBin方法将链表转化为红黑树。

    	final void treeifyBin(Node<K,V>[] tab, int hash) {
            int n, index; Node<K,V> e;
            // 如果桶数组table为空,或者桶数组table的长度小于MIN_TREEIFY_CAPACITY,不符合转化为红黑树的条件
            if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)
                // 数组大小小于64的,调用resize将数组大小扩容至2倍大小
                resize();
            // 如果符合转化为红黑树的条件,而且hash对应的桶不为null, 则重新计算 hash段位,及table的索引位,第一个节点
            else if ((e = tab[index = (n - 1) & hash]) != null) {
                TreeNode<K,V> hd = null, tl = null;
                do {
                    // 遍历链表,将链表元素转化成TreeNode链
                    TreeNode<K,V> p = replacementTreeNode(e, null);
                    // 确定树头节点
                    if (tl == null)
                        // TreeNode链为空,将元素设置为hd的首个节点
                        hd = p;
                    else {
                        // TreeNode链不为空,向TreeNode链后面添加元素
                        p.prev = tl;
                        tl.next = p;
                    }
                    tl = p;
                } while ((e = e.next) != null);
                // 前面仅仅转换为双向链表,treeify才是转换红黑树的处理方法入口 
                // 让桶的第一个元素指向新建的红黑树头结点,以后这个桶里的元素就是红黑树而不是链表了
                if ((tab[index] = hd) != null)
                    // TreeNode链表转化为红黑树
                    hd.treeify(tab);
            }
        }

构成红黑树–treeify 方法

将Treenode链转化成红黑树

    		final void treeify(Node<K,V>[] tab) {
                // root节点
                TreeNode<K,V> root = null;
                // 遍历TreeNode链
                for (TreeNode<K,V> x = this, next; x != null; x = next) {
                    // next 下一个节点
                    next = (TreeNode<K,V>)x.next;
                    // 设置左右节点为空
                    x.left = x.right = null;
                    // 第一次进入循环 root == null,确定头结点,为黑色
                    if (root == null) {
                        // 将根节点的父节点设置位空
                        x.parent = null;
                        // 将根节点设置为黑色
                        x.red = false;
                        //将x 设置为根节点
                        root = x;
                    }
                    // 后面进入循环走的逻辑,x 指向树中的某个节点。 此处为非根节点
                    else {
                        // 获取当前循环节点key
                        K k = x.key;
                        // 获取当前节点 hash
                        int h = x.hash;
                        Class<?> kc = null;
                        // 从根节点开始验证,遍历所有节点跟当前节点 x 比较,调整位置,有点像冒泡排序
                        for (TreeNode<K,V> p = root;;) {
                            // 循环查找当前节点插入的位置并添加节点
                            int dir, ph;
                            // 每个节点的 key
                            K pk = p.key;
                            // hashMap元素的hash值用来表示红黑树中节点数值大小
                            if ((ph = p.hash) > h)
                                // 当前节点值小于根节点,dir = -1 沿左路径查找
                                dir = -1;
                            else if (ph < h)
                                // 当前节点值大于根节点, dir = 1 沿右路径查找
                                dir = 1;
                            // 如果存在比较对象,则根据比较对象定义的comparable进行比较
                			// 比较之后返回查询节点路径(左或右)
                            else if ((kc == null &&
                                      (kc = comparableClassFor(k)) == null) ||
                                     (dir = compareComparables(kc, k, pk)) == 0)
                                // 当前节点的值等于根节点值。
                                // 如果当前节点实现Comparable接口,调用compareTo比较大小并赋值dir
                                // 如果当前节点没有实现Comparable接口,compareTo结果等于0,则调用tieBreakOrder继续比较大小
                                // tieBreakOrder本质是通过比较k与pk的hashcode
                                dir = tieBreakOrder(k, pk);
    						// 当前“根节点”赋值给xp
                            TreeNode<K,V> xp = p;
                            if ((p = (dir <= 0) ? p.left : p.right) == null) {
                                // 如果当前节点小于根节点且左子节点为空 或者  当前节点大于根节点且右子节点为空,直接添加子节点
                                // 将px设置为x的父节点
                                x.parent = xp;
                                if (dir <= 0)
                                    xp.left = x;
                                else
                                    xp.right = x;
                                // 平衡红黑树,将二叉树转换位红黑树-正式转换红黑树
                                root = balanceInsertion(root, x);
                                // 跳出循环,继续向红黑树添加下一个元素
                                break;
                            }
                        }
                    }
                }
                // 确保红黑树根节点是数组中该index的第一个节点
                moveRootToFront(tab, root);
            }

新增元素后平衡红黑树–balanceInsertion方法

    static <K,V> TreeNode<K,V> balanceInsertion(TreeNode<K,V> root,
                                                        TreeNode<K,V> x) {
                // 新增节点默认是红色
                x.red = true;
                // xp父节点 xpp祖父节点 xppl祖父左节点 xppr 祖父右节点
                for (TreeNode<K,V> xp, xpp, xppl, xppr;;) {
                    // xp = x.parent
            		// 如果x存在父节点,则说明目前只有一个节点,即root.根据红黑树的五大特征,根节点只能为黑色节点
                    if ((xp = x.parent) == null) {
                        // x的父节点为空,x应为根节点,应为黑色
                        x.red = false;
                        return x;
                    }
                    // xpp = xp.parent, 直接查询的是根节点
                    else if (!xp.red || (xpp = xp.parent) == null)
                        // 父节点是黑色,祖父节点为空,直接返回
                        return root;
                        
                    // xppl = xpp.left.  x的父节点是左节点时
                    if (xp == (xppl = xpp.left)) {
                        // 验证是否需要旋转
              			// xppr = xpp.right 存在右节点 且 右节点为红色
                        if ((xppr = xpp.right) != null && xppr.red) {
                            // 叔父节点设为黑色
                            xppr.red = false;
                            // 父节点设为黑色
                            xp.red = false;
                            // 祖父节点设置为红色
                            xpp.red = true;
                            // 将祖父节点设置为当前节点,并继续循环操作
                            x = xpp;
                        }
                        else {
                            // 叔父节点为黑色或者空
                            if (x == xp.right) {
                                // x为父节点右节点,则要进行左旋操作
                                root = rotateLeft(root, x = xp);
                                xpp = (xp = x.parent) == null ? null : xp.parent;
                            }
                            // 经过左旋x为左节点
                            if (xp != null) {
                                // 父节点涂成黑色
                                xp.red = false;
                                if (xpp != null) {
                                    // 祖父节点不为空
                                    // 祖父节点设为红色
                                    xpp.red = true;
                                    // 以租父节点为支点右旋转
                                    root = rotateRight(root, xpp);
                                }
                            }
                        }
                    }
                    else {
                        // 验证是否需要旋转
                        if (xppl != null && xppl.red) {
                            // 将叔父节点设为黑色
                            xppl.red = false;
                            // 父节点设为黑色
                            xp.red = false;
                            // 祖父节点设为红色
                            xpp.red = true;
                            // 循环操作
                            x = xpp;
                        }
                        else {
                            if (x == xp.left) {
                                // 右旋
                                root = rotateRight(root, x = xp);
                                xpp = (xp = x.parent) == null ? null : xp.parent;
                            }
                            // x为右节点
                            if (xp != null) {
                                xp.red = false;
                                if (xpp != null) {
                                    xpp.red = true;
                                    // 以祖父节点为支点左旋
                                    root = rotateLeft(root, xpp);
                                }
                            }
                        }
                    }
                }
            }

向红黑树添加元素 – putTreeVal 方法

      final TreeNode<K,V> putTreeVal(HashMap<K,V> map, Node<K,V>[] tab,
                                           int h, K k, V v) {
                Class<?> kc = null;
                boolean searched = false;
                // 获取根节点
                TreeNode<K,V> root = (parent != null) ? root() : this;
                for (TreeNode<K,V> p = root;;) {    
                    // 从root节点开始遍历
                    int dir, ph; K pk;
                    // 通过比较hash大小确定添加元素的位置
                    if ((ph = p.hash) > h)
                        dir = -1;
                    else if (ph < h)
                        dir = 1;
                    else if ((pk = p.key) == k || (k != null && k.equals(pk)))
                        // key相同直接返回
                        return p;
                    else if ((kc == null &&
                              (kc = comparableClassFor(k)) == null) ||
                             (dir = compareComparables(kc, k, pk)) == 0) {
                        if (!searched) {
                            TreeNode<K,V> q, ch;
                            
                            searched = true;
                            // 有相同节点直接返回
                            if (((ch = p.left) != null &&
                                 (q = ch.find(h, k, kc)) != null) ||
                                ((ch = p.right) != null &&
                                 (q = ch.find(h, k, kc)) != null))
                                return q;
                        }
                        dir = tieBreakOrder(k, pk);
                    }
     
                    TreeNode<K,V> xp = p;
                    // 根据dir大小添加元素
                    if ((p = (dir <= 0) ? p.left : p.right) == null) {
                        Node<K,V> xpn = xp.next;
                        // 构建新的treeNode节点
                        TreeNode<K,V> x = map.newTreeNode(h, k, v, xpn);
                        if (dir <= 0)
                            xp.left = x;
                        else
                            xp.right = x;
                        xp.next = x;
                        x.parent = x.prev = xp;
                        if (xpn != null)
                            ((TreeNode<K,V>)xpn).prev = x;
                        // 平衡红黑树并保证root是index处首节点
                        moveRootToFront(tab, balanceInsertion(root, x));
                        return null;
                    }
                }
            }

获取方法–getTreeNode

    // 获取红黑树的指定节点
    final TreeNode<K,V> getTreeNode(int h, Object k) {
    	return ((parent != null) ? root() : this).find(h, k, null);// 从根节点开始查询
    }
    
    // 获取红黑树指定节点
    final TreeNode<K,V> find(int h, Object k, Class<?> kc) {
        // 此节点p就是根节点,进入循环后p代表当前节点
    	TreeNode<K,V> p = this;
    	do {
            // 定义当前节点p的hash值ph、相对位置dir、key
    		int ph, dir; K pk;
            // 获取当前节点的左子节点、右子节点
    		TreeNode<K,V> pl = p.left, pr = p.right, q
            // 表明目标节点在当前节点的左子节点
    		if ((ph = p.hash) > h)
    			p = pl;
            // 表明目标节点在当前节点的右子节点
    		else if (ph < h)
    			p = pr;
            // 当前节点的hash值与目标节点hash值相等,且当前节点的key与目标key相等(equals)
    		else if ((pk = p.key) == k || (k != null && k.equals(pk)))
    			return p;
            // 当前节点的hash值与目标节点hash值相等,且当前节点的key与目标key不相等(equals)
    		else if (pl == null)
    			p = pr;
    		else if (pr == null)
    			p = pl;
            // 当前节点的hash值与目标节点hash值相等,
            // 且当前节点的key与目标key不相等(equals),
            // 且左子节点与右子节点均不为null,目标key实现Comparable接口,且与当前节点比较不为0
    		else if ((kc != null ||
                      (kc = comparableClassFor(k)) != null) && 
                     (dir = compareComparables(kc, k, pk)) != 0)
    			p = (dir < 0) ? pl : pr;
            // 当前节点的hash值与目标节点hash值相等,
            // 且当前节点的key与目标key不相等(equals),
            // 且左子节点与右子节点均不为null,目标key没有实现Comparable接口,
            // 则直接在右子树中查询,这个方法并没有在左子树中循环,因为这是一个递归方法,
            // 先遍历右子树并判断是否查找到,若无则将左子树根节点作为当前节点,不用遍历左子树依然可以覆盖全部情况
    		else if ((q = pr.find(h, k, kc)) != null)
    			return q;
    		else
    			p = pl;
    	} while (p != null);
    		return null;// 未找到,返回null
    	}

红黑树节点的删除–removeTreeNode方法

    		final void removeTreeNode(HashMap<K,V> map, Node<K,V>[] tab,
                                      boolean movable) {
                int n;
                // 判断是否为空,是,直接返回
                if (tab == null || (n = tab.length) == 0)
                    return;
        		// 计算下标
                int index = (n - 1) & hash;
                TreeNode<K,V> first = (TreeNode<K,V>)tab[index], root = first, rl;
                // succ指向删除节点的下一个,pred指向前一个
                TreeNode<K,V> succ = (TreeNode<K,V>)next, pred = prev;
                if (pred == null)
                    // 前一个为空,tab[index] 和 first 指向后一个节点
                    tab[index] = first = succ;
                else
                    // 前一个节点不为空,则前一个节点的后一个节点指向后一个,就是删除当前节点
                    pred.next = succ;
                if (succ != null)
                    // 如果后一个节点不为空,将他的前一个节点,指向当前节点的前一个
                    succ.prev = pred;
                if (first == null) // 为空直接返回
                    return;
                // 根节点存在父节点,说明不是根节点,调用root()获取,确保root时根节点
                if (root.parent != null)
                    root = root.root();
                // 根据节点及其左右孩子,判断当前红黑树节点的数量,进而转换为链表
                if (root == null
                    || (movable
                        && (root.right == null
                            || (rl = root.left) == null
                            || rl.left == null))) {
                    tab[index] = first.untreeify(map);  // too small
                    return;
                }
                // p 要删除的节点,replacement删除后替代他的节点
                // 删除一个中级节点,但是他还有子节点,肯定连接到树上的,此时需要一个节点来顶替他的位置
                TreeNode<K,V> p = this, pl = left, pr = right, replacement;
                // 删除节点,左右孩子都不为空时,遍历
                if (pl != null && pr != null) {
                    TreeNode<K,V> s = pr, sl;
                    // s = pr,是当前节点的右节点开始遍历,找到最后一个左子节点
                    // s是大于当前节点的最小值
                    while ((sl = s.left) != null) // find successor
                        s = sl;
                    // 颜色交换,要删除的节点,替换他的节点
                    boolean c = s.red; s.red = p.red; p.red = c; // swap colors
                    TreeNode<K,V> sr = s.right;
                    TreeNode<K,V> pp = p.parent;
                    // 位置交换
                    // s == pr 意思是大于要删除节点的最小节点,就是他的右节点
                    // 在节点右边都是比它大的,在节点左边都是比它小的
                    // 在当前节点的右边,其右边节点的左边,说明大于当前节点,小于当前节点的右节点,最左边的也就是最靠近当前节点
                    if (s == pr) { // p was s's direct parent
                        p.parent = s;
                        s.right = p;
                    }
                    else {
                        // 当前节点的父节点指向,替换节点的父节点
                        TreeNode<K,V> sp = s.parent;
                        if ((p.parent = sp) != null) {
                            // 判断替换的节点是其父的左右节点,将替换节点的父节点的左或者右节点指向当前节点
                            if (s == sp.left)
                                sp.left = p;
                            else
                                sp.right = p;
                        }
                        // 替换节点的右节点指向删除节点的右节点,删除节点的右节点的父节点,指向替换节点
                        if ((s.right = pr) != null)
                            pr.parent = s;
                    }
                    // 删除节点的左节点置空
                    // 替换节点肯定不存在左节点,不然就不会成为替换节点
                    p.left = null;
                    // 但不一定没有右节点,进行右节点赋值
                    if ((p.right = sr) != null)
                        sr.parent = p;
                    // 将替换节点的左节点指向删除节点的左节点
                    if ((s.left = pl) != null)
                        pl.parent = s;
                    // 替换节点的父节点,指向删除节点的父节点,如果父节点为空,则替换节点作为根节点
                    if ((s.parent = pp) == null)
                        root = s;
                    // 删除节点有父节点,且为父节点的左节点,父节点的左节点指向替换节点,反之亦然
                    else if (p == pp.left)
                        pp.left = s;
                    else
                        pp.right = s;
                    // 替换节点存在右节点,左节点是肯定不存在的
                    // replacement 为替换节点右节点,反之为删除节点
                    if (sr != null)
                        replacement = sr;
                    else
                        replacement = p;
                }
                // 删除节点存在左节点,replacement为左节点
                else if (pl != null)
                    replacement = pl;
                // 删除节点存在右节点,replacement为右节点
                else if (pr != null)
                    replacement = pr;
                // 左右节点都不存在,replacement为删除节点
                else
                    replacement = p;
                // replacement不为删除节点(他有子节点,或者s节点有右节点)
                // 看replacement的赋值p的情况
                // 		p节点不存在子节点
                // 		p节点存在左右节点,且s节点无右节点
                if (replacement != p) {
                    // 替换节点的父节点指向当前节点的父节点
                    TreeNode<K,V> pp = replacement.parent = p.parent;
                    // replacement 替换 p
                    // 存在左右节点是,此时的p为替换之后的节点,replacement为sr(替换p的节点的右节点)
                    // 存在左节点,或者右节点,那他的子节点替换p节点
                    if (pp == null)
                        // 如果父节点为null,替换节点为root节点
                        root = replacement;
                    else if (p == pp.left)
                        pp.left = replacement;
                    else
                        pp.right = replacement;
                    // 孤立p节点
                    p.left = p.right = p.parent = null;
                }
    			// p节点为红色,删除后无影响,不为红色需要进行平衡
                TreeNode<K,V> r = p.red ? root : balanceDeletion(root, replacement);
    			// p 没有儿子或者s没有儿子,直接移除p
                if (replacement == p) {  // detach
                    TreeNode<K,V> pp = p.parent;
                    p.parent = null;
                    if (pp != null) {
                        if (p == pp.left)
                            pp.left = null;
                        else if (p == pp.right)
                            pp.right = null;
                    }
                }
                // 处理根节点
                if (movable)
                    moveRootToFront(tab, r);
            }

删除元素后的平衡红黑树–balanceDeletion

    static <K,V> TreeNode<K,V> balanceDeletion(TreeNode<K,V> root,
                                                       TreeNode<K,V> x) {
                for (TreeNode<K,V> xp, xpl, xpr;;) {
                    // 要删除的节点是根节点,或者为null,返回根节点
                    if (x == null || x == root)
                        return root;
                    // x为根节点,设为黑色,返回
                    else if ((xp = x.parent) == null) {
                        x.red = false;
                        return x;
                    }
                    // 删除的节点是红色,无需调整
                    else if (x.red) {
                        x.red = false;
                        return root;
                    }
                    // 移除的节点是其父的左节点
                    else if ((xpl = xp.left) == x) {
                        // 兄弟为红色
                        if ((xpr = xp.right) != null && xpr.red) {
                            // 兄弟设为黑色
                            xpr.red = false;
                            // 父节点为红色
                            xp.red = true;
                            // 左旋
                            root = rotateLeft(root, xp);
                            // 重新将xp指向x的父节点,xpr指向xp新的右孩子
                            xpr = (xp = x.parent) == null ? null : xp.right;
                        }
                        // 没有兄弟节点,将x指向父节点,向上调整
                        if (xpr == null)
                            x = xp;
                        else {
                            // 存在兄弟节点,进一步调整
                            // xpr是兄弟节点兄弟
                            TreeNode<K,V> sl = xpr.left, sr = xpr.right;
                            // 侄子为空或者侄子为黑(没有就算黑)
                            if ((sr == null || !sr.red) &&
                                (sl == null || !sl.red)) {
                                // 兄弟节点设为红色,将x指向父节点
                                xpr.red = true;
                                x = xp;
                            }
                            // 侄子节点存在红色节点
                            else {
                                // 兄弟右节点为空或者黑子,说明兄弟左节点为红色
                                if (sr == null || !sr.red) {
                                    // 兄弟左节点设置黑色
                                    if (sl != null)
                                        sl.red = false;
                                    // 兄弟节点设为红色
                                    xpr.red = true;
                                    // 基于兄弟节点右旋
                                    root = rotateRight(root, xpr);
                                    // 兄弟节点重新指向
                                    xpr = (xp = x.parent) == null ?
                                        null : xp.right;
                                }
                                // 如果兄弟节点不为空
                                if (xpr != null) {
                                    // 让兄弟节点跟父节点同时
                                    xpr.red = (xp == null) ? false : xp.red;
                                    // 兄弟右节点不为空,设置黑色
                                    if ((sr = xpr.right) != null)
                                        sr.red = false;
                                }
                                // 存在父节点
                                if (xp != null) {
                                    xp.red = false;// 设置黑色
                                    root = rotateLeft(root, xp);// 基于父节点左旋
                                }
                                x = root;
                            }
                        }
                    }
                    // x为右节点,与上面类似判断节点颜色,颜色变化与旋转
                    else { // symmetric
                        if (xpl != null && xpl.red) {
                            xpl.red = false;
                            xp.red = true;
                            root = rotateRight(root, xp);
                            xpl = (xp = x.parent) == null ? null : xp.left;
                        }
                        if (xpl == null)
                            x = xp;
                        else {
                            TreeNode<K,V> sl = xpl.left, sr = xpl.right;
                            if ((sl == null || !sl.red) &&
                                (sr == null || !sr.red)) {
                                xpl.red = true;
                                x = xp;
                            }
                            else {
                                if (sl == null || !sl.red) {
                                    if (sr != null)
                                        sr.red = false;
                                    xpl.red = true;
                                    root = rotateLeft(root, xpl);
                                    xpl = (xp = x.parent) == null ?
                                        null : xp.left;
                                }
                                if (xpl != null) {
                                    xpl.red = (xp == null) ? false : xp.red;
                                    if ((sl = xpl.left) != null)
                                        sl.red = false;
                                }
                                if (xp != null) {
                                    xp.red = false;
                                    root = rotateRight(root, xp);
                                }
                                x = root;
                            }
                        }
                    }
                }
            }

HashMap对左旋右旋的实现

左旋
           	//root为根节点,p为旋转的结点
    		static <K,V> TreeNode<K,V> rotateLeft(TreeNode<K,V> root,TreeNode<K,V> p) {
                // r当前节点的右节点
                // pp当前节点的父节点
                // rl当前节点的右节点的左节点
                TreeNode<K,V> r, pp, rl;
                //如果p不为空且存在右子结点r
                if (p != null && (r = p.right) != null) { 
                    //判断右子结点的左子结点rl存在
                    if ((rl = p.right = r.left) != null)    
                        //存在设置rl的父节点为p
                        rl.parent = p;  
                    //判断p的父节点pp是否存在
                    if ((pp = r.parent = p.parent) == null) 
                        //如果不存在设置新的根节点为r且黑色
                        (root = r).red = false; 
                    //父结点pp存在且p为pp的左子结点
                    else if (pp.left == p)                 
                        pp.left = r;
                    else 
                        //父结点pp存在且p为pp的左子结点
                        pp.right = r;
                    r.left = p;
                    p.parent = r;
                }
                return root;
            }
右旋
           //root为根节点,p为旋转的结点
    	static <K,V> TreeNode<K,V> rotateRight(TreeNode<K,V> root,TreeNode<K,V> p) {
            // r当前节点的左节点
            // pp当前节点的父节点
            // rl当前节点的左节点的右节点
            TreeNode<K,V> l, pp, lr;
            //如果p不为空且存在左子结点l
            if (p != null && (l = p.left) != null) { 
                //判断左子结点的右子结点lr存在
                if ((lr = p.left = l.right) != null)   
                    //存在则设置rl的父结点为p
                    lr.parent = p;   
                //判断p的父结点pp是否存在
                if ((pp = l.parent = p.parent) == null)
                    //如果不存在设置新的根节点为l且l为黑色
                    (root = l).red = false;
                else if (pp.right == p)              
                    //父结点pp存在且p为pp的右子结点
                    pp.right = l;
                else                                 
                    //父结点pp存在且p为pp的左子结点
                    pp.left = l;
                l.right = p;
                p.parent = l;
            }
            return root;
        }
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值