HashMap红黑树插入源码注解分析

HashMap红黑树插入源码注解分析

小龙 645 2021-03-02

红黑树02.png

/**
     * 红黑树插入操作
     * @param root 根节点
     * @param x 新插入节点
     * @return
     */
    static <K,V> HashMap.TreeNode<K,V> balanceInsertion(HashMap.TreeNode<K,V> root,
                                                        HashMap.TreeNode<K,V> x) {
        // 新节点默认为红色
        x.red = true;
        /**
         * xp:表示新节点的父节点
         * xpp:表示新节点的祖父节点
         * xppl:表示祖父节点的左子节点
         * xppr:表示祖父节点的右子节点
         */
        for (HashMap.TreeNode<K,V> xp, xpp, xppl, xppr;;) {
            // 如果新节点的父节点为空,则新节点就是根节点
            if ((xp = x.parent) == null) {
                // 将颜色设置为黑色
                x.red = false;
                return x;// 返回这个节点
            }
            //如果父节点是黑色,或祖父节点为空
            else if (!xp.red || (xpp = xp.parent) == null)
                //直接返回根节点
                return root;
            //如果父节点等于祖父节点的左子节点
            if (xp == (xppl = xpp.left)) {
                // 如果祖父节点的右节点不为空,并且叔叔节点是红色的
                if ((xppr = xpp.right) != null && xppr.red) {
                    xppr.red = false; // 叔叔节点变为黑色
                    xp.red = false; // 父节点变为黑色
                    xpp.red = true; // 祖父节点变为红色
                    x = xpp; // 祖父节点变为新节点X
                }
                // 叔叔节点为空,或者叔叔节点时黑色的
                else {
                    // 如果新节点等于父节点的有子节点
                    if (x == xp.right) {
                        // 先将新节点的父节点左旋
                        root = rotateLeft(root, x = xp);
                        // 左旋完结构xpp(pp) -> xp(r,原来的新节点) -> x(p,原理新节点的父节点)
                        xpp = (xp = x.parent) == null ? null : xp.parent;
                    }
                    // 如果xp不为空
                    if (xp != null) {
                        // xp变为黑色
                        xp.red = false;
                        // 如果xpp不为空
                        if (xpp != null) {
                            // xpp变为红色
                            xpp.red = true;
                            // 将新节点X的祖父节点xpp右旋
                            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;
                    }
                    if (xp != null) {
                        xp.red = false;
                        if (xpp != null) {
                            xpp.red = true;
                            root = rotateLeft(root, xpp);
                        }
                    }
                }
            }
        }
    }

    /**
     * 负责节点左旋
     * @param root 根节点
     * @param p == px,新节点的父节点
     * @return
     */
    static <K,V> HashMap.TreeNode<K,V> rotateLeft(HashMap.TreeNode<K,V> root,
                                                  HashMap.TreeNode<K,V> p) {
        /**
         * r:p的右子节点,就是外面的新节点X
         * pp:就是外面的ppx,新节点的祖父节点
         * rl:r的左子节点
         */
        HashMap.TreeNode<K,V> r, pp, rl;
        // 判断传入的p不为空,并且p的右子节点也不为空,将p的由子节点赋值给r,这个r其实就是外面的新节点X
        if (p != null && (r = p.right) != null) {
            // 将 r 的左子节点赋值给 p 的右子节点,并赋值给 rl,如果rl不为空(r的右子节点不为空),将rl的父节点设置为p
            if ((rl = p.right = r.left) != null)
                //rl的父节点设置为p
                rl.parent = p;
            // 将r的父节点设置为p的父节点,并赋值给pp,pp就是外面的xpp,X新节点的祖父节点,如果这个节点为空
            if ((pp = r.parent = p.parent) == null)
                // 将r设置为根节点,并变成黑色
                (root = r).red = false;
            // pp不为空,如果pp的左子节点等于p
            else if (pp.left == p)
                // pp的左子节点这是为r
                pp.left = r;
            // pp的左子节点不等于p
            else
                // pp的右子节点设置为r
                pp.right = r;
            // r的左子节点这是为p
            r.left = p;
            // 拍的父节点设置为r
            p.parent = r;
        }
        return root;
    }

    /**
     * 负责节点的右旋
     * @param root 根节点
     * @param p 是外面的xpp节点
     * @return
     */
    static <K,V> HashMap.TreeNode<K,V> rotateRight(HashMap.TreeNode<K,V> root,
                                                   HashMap.TreeNode<K,V> p) {
        /**
         * l:p.left,p节点的左子节点
         * pp:p的父节点
         * lr:是l的右子节点
         */
        HashMap.TreeNode<K,V> l, pp, lr;
        if (p != null && (l = p.left) != null) {
            if ((lr = p.left = l.right) != null)
                lr.parent = p;
            if ((pp = l.parent = p.parent) == null)
                (root = l).red = false;
            else if (pp.right == p)
                pp.right = l;
            else
                pp.left = l;
            l.right = p;
            p.parent = l;
        }
        return root;
    }

红黑树01.png