简介

红黑树(Red Black Tree) 是一种自平衡二叉查找树,是在计算机科学中用到的一种数据结构,典型的用途是实现关联数组。
它是在1972年由Rudolf Bayer发明的,当时被称为平衡二叉B树(symmetric binary B-trees)。后来,在1978年被 Leo J. Guibas 和 Robert Sedgewick 修改为如今的“红黑树”

红黑树和AVL树类似,都是在进行插入和删除操作时通过特定操作保持二叉查找树的平衡,从而获得较高的查找性能。
它虽然是复杂的,但它的最坏情况运行时间也是非常良好的,并且在实践中是高效的: 它可以在O(log n)时间内做查找,插入和删除,这里的n 是树中元素的数目。

它的统计性能要好于平衡二叉树(有些书籍根红黑树据作者姓名,Adelson-Velskii和Landis,将其称为AVL-树),因此,红黑树在很多地方都有应用。在C++ STL中,很多部分(包括set, multiset, map, multimap)应用了红黑树的变体(SGI STL中的红黑树有一些变化,这些修改提供了更好的性能,以及对set操作的支持)。其他平衡树还有:AVL,SBT,伸展树,TREAP 等等。

红黑树是每个节点都带有颜色属性的二叉查找树,颜色或红色或黑色。在二叉查找树强制一般要求以外,对于任何有效的红黑树我们增加了如下的额外要求:
    性质1. 节点是红色或黑色。
    性质2. 根节点是黑色。
    性质3 每个叶节点(NIL节点,空节点)是黑色的。
    性质4 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)
    性质5. 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。
这些约束强制了红黑树的关键性质: 从根到叶子的最长的可能路径不多于最短的可能路径的两倍长。结果是这个树大致上是平衡的。
因为操作比如插入、删除和查找某个值的最坏情况时间都要求与树的高度成比例,这个在高度上的理论上限允许红黑树在最坏情况下都是高效的,而不同于普通的二叉查找树。
要知道为什么这些特性确保了这个结果,注意到性质4导致了路径不能有两个毗连的红色节点就足够了。最短的可能路径都是黑色节点,最长的可能路径有交替的红色和黑色节点。因为根据性质5所有最长的路径都有相同数目的黑色节点,这就表明了没有路径能多于任何其他路径的两倍长。



其在jdk中经典的使用在于TreeMap, jdk1.8 中对于HashMap加入了红黑树相关的优化 [如果某个桶中的记录过 大的话(当前是TREEIFY_THRESHOLD = 8),HashMap会动态的使用一个专门的treemap实现来替换掉它。这样做的结果会更好,是O(logn),而不是糟糕的O(n)。]

其实对于这个数据结构, 我现在就只记得他的添加元素, 删除元素需要维护其性质的话, 情况比较多, 比较复杂, 还有其适合于查找[给定的元素, 比给定元素大的最小元素, 比给定元素小的最大的元素] 或者 以及需要将输入构造为有序的序列的场景

下面的参考代码是参考 “” 的来编写的
至于 其他的介绍, 这里就不介绍了, 因为有很多相关的播客嘛, 这个当时可是花了我三四天的时间啊。。
参考中 也有一些不错的播客,
jdk 中TreeMap的实现是相当简洁优雅的。。

参考代码

/**
 * file name : Test18BRTree.java
 * created at : 9:12:45 PM Jun 1, 2015
 * created by 
 */

package com.hx.test04;

import com.hx.util.Log;
import com.hx.util.Tools;

public class Test18BRTree {

    // 红黑树
    // 参考 : 
    public static void main(String []args) {

//      int[] arr = new int[] {34, 18, 28, 22, 32, 38, 27, 19, 17, 11, 38, 37, 48, 48, 6 };
        int[] arr = new int[] {34, 18, 28, 22 };

        BlackRedTree brt = new BlackRedTree();
        for(int i=0; i<arr.length; i++) {
            brt.add(arr[i]);
        }
        Log.log(brt);


    }

    // 红黑树
//    1.节点是红色或黑色。 
//    2.根是黑色。 
//    3.所有叶子(外部节点)都是黑色。 
//    4.每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点) 
//    5.从每个叶子到根的所有路径都包含相同数目的黑色节点。 
    static class BlackRedTree {
        // 根节点
        Node root;

        // 初始化
        public BlackRedTree() {
            root = null;
        }

        // 添加一个元素  先插入在检查是否需要转动结点
        // 如果root为null  则说明该树还没有结点  新建一个root结点, 设置其颜色为BLACK
        // 否则 插入一个结点  在检查是否 需要扭转结点  来使得满足其性质
        public void add(int val) {
            if(root == null) {
                root = new Node();
                root.setColor(Node.BLACK);
                root.val = val;
            } else {
                Node node = root;

                Node newNode = insert(val);

                fixAfterInsert01(newNode);
//              fixAfterInsert02(newNode);
            }
        }

        public void remove(int val) {

            Node[] tmp = delete(val);

            // 如果没有找到对应值的结点, 或者该节点为root 并且没有左右孩子
            // 不知道delete中对tmp的控制  和这里的确保deleted不为叶子结点的控制是否有问题, 一会儿再来看看吧
            if(tmp != null) {
                fixAfterDelete01(tmp[0], tmp[1]);
            }

        }

        // 移除结点node 
        // 方式二 : 将node结点的左子树的最大结点[或者右子树的最小节点] 替换掉node, 然后该结点的左子树接到该节点的父节点上
        private Node remove1(Node node) {
            if(isLeft(node) ) {
                return removeForNode1Left(node);
            } else {
                return removeForNode1Right(node);
            }
        }

        // 删除root结点 方式一 :  找出root结点左孩子的最大值  替换掉root结点,  然后该结点的左子树接到该节点的父节点上
        private Node removeForRoot0(Node node) {
            return removeForNode1Left(root);
        }

        // 删除root结点 方式二 : 将root结点的右子树的最小结点 替换掉root, 然后该结点的右子树接到该节点的父节点上
        private Node removeForRoot1(Node node) {
            return removeForNode1Right(root);
        }

        // 删除结点 方式二[Left] :  找出左孩子的最大值  替换掉删除结点,  然后该结点的左子树接到该节点的父节点上
        private Node removeForNode1Left(Node node) {
            Node nodeLeftMax = getMaxNode(node.left);
            node.val = nodeLeftMax.val;

            if(nodeLeftMax.parent == node) {
                node.left = nodeLeftMax.left;
                if(nodeLeftMax.left != null) {
                    nodeLeftMax.left.parent = node;
                }
            } else {
                nodeLeftMax.parent.right = nodeLeftMax.left;
                if(nodeLeftMax.left != null) {
                    nodeLeftMax.left.parent = nodeLeftMax.parent;
                }   
            }

            return nodeLeftMax;
        }

        // 删除root结点 方式二[Right] : 将node结点的右子树的最小结点 替换掉node, 然后该结点的右子树接到该节点的父节点上
        private Node removeForNode1Right(Node node) {
            Node nodeRightMin = getMinNode(node.right);
            node.val = nodeRightMin.val;

            if(nodeRightMin.parent == node) {
                node.right = nodeRightMin.right;
                if(nodeRightMin.right != null) {
                    nodeRightMin.right.parent = node;
                }
            } else {
                nodeRightMin.parent.left = nodeRightMin.right;
                if(nodeRightMin.right != null) {
                    nodeRightMin.right.parent = nodeRightMin.parent;
                }
            }

            return nodeRightMin;
        }

        // 获取node结点的最大子节点
        private Node getMaxNode(Node node) {
            Node tmp = node;
            while(tmp.right != null) {
                tmp = tmp.right;
            }

            return tmp;
        }

        // 获取node结点的最小子节点
        private Node getMinNode(Node node) {
            Node tmp = node;
            while(tmp.left != null) {
                tmp = tmp.left;
            }

            return tmp;
        }

        // 遍历树 获取val对应的结点
        public Node get(int val) {
            Node node = root;

            while(node != null) {
                if(val < node.val ) {
                    node = node.left;
                } else if(val > node.val ) {
                    node = node.right;
                } else {
                    return node;
                }
            }

            return null;
        }

        // 检查是否需需要扭转结点   来满足其性质
        // 令cur为加入的结点, parent为加入结点的父节点, gParent为加入节点的祖父节点, uncle为cur的舅舅结点[父节点的兄弟结点]
        // 如果cur结点不是root 并且是红色
            // 如果parent 是黑色的   则直接返回, 插入当前结点 没有破坏红黑树的性质
            // 否则  这时候就说明了gParent节点不为空[因为parent节点为红色 不可能是root结点] 
            // 这是候  获取uncle结点   
                // 如果uncle结点为红色的时候[uncle结点为空  视为黑色]    设置gParent结点为红色, uncle, parent结点为黑色, 令更新cur为gParent结点   继续下一次的循环
                // 如果uncle结点为 黑色         这时候有四种情况[因为uncle为黑色  调整之后  cur结点为black  所以会跳出while]
                    // 1) 如果parent结点是gParent结点的左结点 并且cur结点是parent结点的左结点     这时候将parent结点右旋转   并设置parent为黑色, 设置parent的两个子节点为红色
                    // 2) 如果parent结点是gParent结点的右结点 并且cur结点是parent结点的右结点     这时候将parent结点左旋转    并设置parent为黑色, 设置parent的两个子节点为红色
                    // 3) 如果parent结点是gParent结点的左结点 并且cur结点是parent结点的右结点     这时候先将cur结点左旋转, 在讲cur结点右旋转    并设置cur为黑色, 设置cur的两个子节点为红色
                    // 4) 如果parent结点是gParent结点的右结点 并且cur结点是parent结点的左结点     这时候先将cur结点右旋转, 在讲cur结点左旋转    并设置cur为黑色, 设置cur的两个子节点为红色
        // 参考 : http://blog.163.com/fulei.20030727@126/blog/static/300662212007112205334389/
        private void fixAfterInsert01(Node newNode) {
            Node parent, gParent;
            Node cur = newNode;

            //we should fix until it is black colored
            while(cur != root && isRed(cur) ) {
                parent=cur.parent;
                if(parent.isBlack() ) {
                    //that's fine, the insertion will not change any black height, and will not violate any rule.
                    return;
                }
                gParent = parent.parent;//we can assume the p is not null now.

                Node uncle = getUncle(parent);
                if(uncle != null && uncle.isRed() ) {
                    //re-coloring
                    gParent.setColor(Node.RED);
                    uncle.setColor(Node.BLACK);
                    parent.setColor(Node.BLACK);

                    //now the g maybe conflict with its parent;
                    cur = gParent;
                } else {
                    if(isLeft(parent) ) {
                        if(isRight(cur)) {
                            //this case we should do left rotation, and then it will transform to next case
                            leftRotate(cur);
                            //transformed to next case    
//                          cur = cur.left;
                        } else {
                            cur = parent;
                        }

                        rightRotate(cur);
                    } else {
                        if(isLeft(cur)) {
                            //this case we should do right rotation, and then it will transform to next case
                            rightRotate(cur);
                            //transformed to next case    
//                          cur = cur.right;
                        } else {
                            cur = parent;
                        }

                        leftRotate(cur);
                    }

                    cur.setColor(Node.BLACK);
                    setNodeToColorIfNotNull(cur.left, Node.RED);
                    setNodeToColorIfNotNull(cur.right, Node.RED);
                }

            }

            root.setColor(Node.BLACK);
        }

        // 思路 和上面基本一致, 不过这里面部分代码是  我之前自己敲的, 而上面是  参考网上一位网友的作品
        // 这个算法  我是没有完成的, 是参考过上面的代码之后 改进的
        // 我的主要的漏洞在于  对于叔叔结点为红色的处理,我不知要需要循环/ 递归 处理, 所以我当时的处理方式   就是直接旋转gParent结点了,,, 擦  没有参考别人的东西, 要思考多久才能想出来....
        private void fixAfterInsert02(Node newNode) {
            while(newNode != root && isRed(newNode)) {
                Node last = newNode.parent;
                // 如果  加入结点的父节点为黑色  说明满足BRTree的条件
                if(last.isBlack() ) {

                    break;
                } else {
                    Node uncle = getUncle(last);
                    // 如果叔叔结点时红色
                    if(uncle != null && uncle.isRed()) {
                        last.parent.setColor(Node.RED);
                        last.setColor(Node.BLACK);
                        uncle.setColor(Node.BLACK);

                        newNode = last.parent;

                        // 更新gParent, parent, uncle结点的颜色  并旋转gParent结点 [思路就错了,,,]
    //                  Node lpParent = last.parent.parent;
    //              
    //                  if(lpParent != null) {
    //                      last.transColor();
    //                      last.parent.transColor();
                            Node uncle = getUncle(last);
    //                      if(uncle != null) {
    //                          uncle.transColor();
    //                      }
    //                      
    //                      lpParent.transColor();
    //                      lpParent.parent.transColor();
    //                      if(isLeft(lpParent) ) {
    //                          if(lpParent.parent != null) {
    //                              transColorForAllSubTree(lpParent.parent.right);
    //                          }
    //                          rightRotate(lpParent);
    //                      } else {
    //                          if(lpParent.parent != null) {
    //                              transColorForAllSubTree(lpParent.parent.left);
    //                          }
    //                          leftRotate(lpParent);
    //                      }
    //                  } else {
    //                      if(last.isRed) {
    //                          newNode.setColor(Node.BLACK);
    //                      }
    //                  }

                        // useless   当现在  root结点的左子树和右子树  深度相差大于1的时候    将其深度大的一方向深度小的一方旋转..
    //                  int maxLeft = this.getMaxDepth(root.left, 0);
    //                  int maxRight = this.getMaxDepth(root.right, 0);
                        Log.log(maxLeft, maxRight);
    //                  if(maxLeft > maxRight + 1) {
    //                      root.transColor();
    //                      root.left.transColor();
    //                      rightRotate(root.left);
    //                  } else if(maxRight > maxLeft + 1) {
    //                      root.transColor();
    //                      root.right.transColor();
    //                      leftRotate(root.right);
    //                  }
                        // 如果叔叔结点时黑色
                    } else {
                        if(isLeft(last) && isLeft(newNode) ) {
                            rightRotate(last);
                            newNode = last;
                        } else if(isRight(last) && isRight(newNode) ) {
                            leftRotate(last);
                            newNode = last;
                        } else if(isLeft(last) && isRight(newNode) ) {
                            leftRotate(newNode);
                            rightRotate(newNode);
                        } else {
                            rightRotate(newNode);
                            leftRotate(newNode);
                        }

                        newNode.setColor(Node.BLACK);
                        setNodeToColorIfNotNull(newNode.left, Node.RED);
                        setNodeToColorIfNotNull(newNode.right, Node.RED);
                    } 

                }
            // end of while
            }

            root.setColor(Node.BLACK);
        }

        // 删除结点之后的调整操作
            // 如果删除结点是红色  则不影响性质
            // 否则 deleted 结点必然只有一个孩子结点 或者没有子节点[详见delete方法]
                // 获取deleted 结点的子节点
                // 如果其 没有子节点   则加入一个临时结点   该临时结点的父节点指向deleted的父节点[主要是为了之后的调整操作占一个位置]
            // 然后进行调整根据son结点是parent结点的左孩子 或者右孩子进行调整
            // 最后  如果添加了临时结点  则 删除临时结点
        private void fixAfterDelete01(Node tar, Node deleted) {
            if(deleted.isRed()) {
                return ;
            } else {
                Node son = null;
                boolean isLeft = false;
                boolean isSonExists = false;

                son = getSonIfOnlyOneNode(deleted);
                if(son != null) {
                    isSonExists = true;
                    isLeft = isLeft(son);
                // 处理删除结点没有孩子的情况  添加一个临时结点
                } else {
                    Node tmpNode = new Node(deleted.parent, -1);
                    tmpNode.setColor(Node.BLACK);
                    isLeft = deleted.val < deleted.parent.val;
                    if(isLeft) {
                        deleted.parent.left = tmpNode;
                    } else {
                        deleted.parent.right = tmpNode;
                    }
                    son = tmpNode;
                }
                // 如果删除的结点是黑色  并且其孩子结点是红色, 直接领该孩子结点为黑色   即调整完毕
                if(son.isRed() ) {
                    son.setColor(Node.BLACK);
                    return ;
                }

//              Log.log(son);
                if(isLeft ) {
                    fixAfterDelete01Left(son);
                } else {
                    fixAfterDelete01Right(son);
                }
//              Log.log(son);Log.horizon();

                // 如果删除的结点 没有子节点, 则这里最后的时候  删除临时结点
                if(!isSonExists) {
                    if(isLeft ) {
                        son.parent.left = null;
                    } else {
                        son.parent.right = null;
                    }
                }
            }

        }

        // 如果son是parent结点的左结点   调整方案如下
            // 先获取parent, sibling结点[相对于son结点]
            // 步骤1 : 如果sibling结点是红色                                                                               则将sibling结点和parent结点互换颜色, 并对sibling结点进行左旋转操作, 更新sibling结点
            // 步骤2    :如果sibling的左右子节点均为黑色[sibling结点为空也算]   设置sibling结点的颜色为黑色, 并调整son结点为其父节点
                // 如果现在的son结点为红色, 则说明调整完成   返回
                // 否则更新parent, sibling结点   继续循环, 执行步骤1, 步骤2, ...
                // 如果son结点回溯到了  root结点  则调整完成
            // 步骤3    : 如果sibling的左右子节点不全为黑色,  如果sibling的子节点  左红右黑            将sibling左子结点设置为黑色, 并设置sibling结点的颜色为红色, 并将sibling左子结点右旋转, 更新sibling结点
            // 步骤4    :此时sibling结点的右节点必然为红[可能经过步骤3的处理, 也可能没有]      将sibling结点的右子节点设置为黑色, 交换sibling, parent结点的颜色, 在讲sibling结点左旋转, 完成调整
        // 参考 : 
        private void fixAfterDelete01Left(Node son) {
            // 接下来的情况是删除结点为黑色  并且son结点为黑色的情况
            Node parent = son.parent;
            Node sibling = getUncle(son);

            while(son != root) {
                // step 1 : 如果son的兄弟结点为红色的话   交换sibling和parent的颜色  并将sibling结点左旋转
                // 更新sibling结点为son现在的兄弟节点
                if(sibling.isRed() ) {
                    boolean isRed = parent.isRed();
                    parent.setColor(sibling.isRed() );
                    sibling.setColor(isRed );
                    leftRotate(sibling);
                    sibling = getUncle(son);
                }

                // step 2 : 如果 sibling的左右结点均为黑色
                if(sibling == null || (isBlack(sibling.left) && isBlack(sibling.right)) ) {
                    sibling.setColor(Node.RED);
                    son = son.parent;
                    if(son.isRed() ) {
                        son.setColor(Node.BLACK);
                        return ;
                    }

                    parent = son.parent;
                    sibling = getUncle(son);
                } else {
                    break;
                }
            }
            // son 结点回溯到了root结点   直接返回
            if(son == root) {
                return ;
            }

            // step 3 : sibling的子节点不是全黑色   而是左红右黑
            if(isRed(sibling.left) && isBlack(sibling.right) ) {
                setNodeToColorIfNotNull(sibling.left, Node.BLACK);
                sibling.setColor(Node.RED);
                rightRotate(sibling.left);
                sibling = getUncle(son);
            }

            // step 4 : 处理w右子节点y为红色的情况,此时w的左子节点x可黑可红
            setNodeToColorIfNotNull(sibling.right, Node.BLACK);
            boolean isRed = parent.isRed();
            parent.setColor(sibling.isRed() );
            sibling.setColor(isRed );
            leftRotate(sibling);
        }

        // 如果son是parent结点的右结点   调整方案和son为parent结点的左结点的调整是对称的, 所以逻辑基本一致
        private void fixAfterDelete01Right(Node son) {
            // 接下来的情况是删除结点为黑色  并且son结点为黑色的情况
            Node parent = son.parent;
            Node sibling = getUncle(son);

            while(son != root) {
                // step 1 : 如果son的兄弟结点为红色的话   交换sibling和parent的颜色  并将sibling结点左旋转
                // 更新sibling结点为son现在的兄弟节点
                if(sibling.isRed() ) {
                    boolean isRed = parent.isRed();
                    parent.setColor(sibling.isRed() );
                    sibling.setColor(isRed );
                    rightRotate(sibling);
                    sibling = getUncle(son);
                }

                // step 2 : 如果 sibling的左右结点均为黑色
                if(sibling == null || (isBlack(sibling.left) && isBlack(sibling.right)) ) {
                    sibling.setColor(Node.RED);
                    son = son.parent;
                    if(son.isRed() ) {
                        son.setColor(Node.BLACK);
                        return ;
                    }

                    parent = son.parent;
                    sibling = getUncle(son);
                } else {
                    break;
                }
            }
            // son 结点回溯到了root结点  这说明调整完成   直接返回
            if(son == root) {
                return ;
            }

            // step 3 : sibling的子节点不是全黑色   而是左红右黑
            if(isRed(sibling.right) && isBlack(sibling.left) ) {
                setNodeToColorIfNotNull(sibling.left, Node.RED);
                sibling.setColor(Node.BLACK);
                leftRotate(sibling.right);
                sibling = getUncle(son);
            }

            // step 4 : 处理w右子节点y为红色的情况,此时w的左子节点x可黑可红
            setNodeToColorIfNotNull(sibling.left, Node.BLACK);
            boolean isRed = parent.isRed();
            parent.setColor(sibling.isRed() );
            sibling.setColor(isRed );
            rightRotate(sibling);
        }

        // 获取deleted结点的子节点    优先获取左子结点
        private Node getSonIfOnlyOneNode(Node deleted) {
            return deleted.left != null ? deleted.left : deleted.right;
        }

        // 将node结点视为红色的情况
        private boolean isRed(Node node) {
            return node != null && node.isRed();
        }

        // 将node结点视为黑色的情况
        private boolean isBlack(Node node) {
            return node == null || node.isBlack();
        }

        // 设置 node结点的颜色为isRed
        private void setNodeToColorIfNotNull(Node node, boolean isRed) {
            if(node != null) {
                node.setColor(isRed);
            }
        }

        // 以二叉排序树的规则 将val插入树中  不做任何其他操作
        // 返回 插入的结点
        private Node insert(int val) {
            Node node = root;
            Node last = null;

            while(node != null) {
                last = node;
                if(val < node.val ) {
                    node = node.left;
                } else if(val > node.val ) {
                    node = node.right;
                } else {
                    Log.log(val + " is already exists...");
                    return null;
                }
            }

            Node newNode = null;
            if(val < last.val) {
                newNode = new Node(last, val);
                last.left = newNode;
            } else {
                newNode = new Node(last, val);
                last.right = newNode;
            }

            return newNode;
        }

        // 删除val对应的结点   返回需要删除的结点 和真正删除的结点
        private Node[] delete(int val) {
            Node node = get(val);
            if(node == null) {
                Log.log("val " + val + " is no exist...");
                return null;
            }
            Node[] tmp = new Node[2];
            tmp[0] = node;  tmp[1] = node;
            if(node.parent == null) {
                if(isLeaf(node)) {
                    root = null;
                    tmp = null;
                } else if(node.left != null) {
                    tmp[1] = removeForRoot0(node);
                } else if(node.right != null) {
                    tmp[1] = removeForRoot1(node);
                }

                return tmp;
            } else {
                if(isLeaf(node)) {
                    if(isLeft(node)) {
                        node.parent.left = null;
                    } else {
                        node.parent.right = null;
                    }
                } else if(node.left != null && node.right != null) {
//                  remove0(node);
                    tmp = new Node[2];
                    tmp[0] = node;
                    tmp[1] = remove1(node);
                } else if(node.left != null) {
                    if(isLeft(node)) {
                        node.parent.left = node.left;
                        node.left.parent = node.parent;
                    } else {
                        node.parent.right = node.left;
                        node.left.parent = node.parent;
                    }
                } else if(node.right != null) {
                    if(isLeft(node)) {
                        node.parent.left = node.right;
                        node.right.parent = node.parent;
                    } else {
                        node.parent.right = node.right;
                        node.right.parent = node.parent;
                    }
                }

                return tmp;
            }
        }

//      // 更新整棵子树的结点的颜色
//      private void transColorForAllSubTree(Node node) {
//          node.transColor();
//          if(node.left != null) {
//              transColorForAllSubTree(node.left);
//          }
//          if(node.right != null) {
//              transColorForAllSubTree(node.right);
//          }
//      }

        // 右旋转last结点
        private void rightRotate(Node last) {
            Node lpParent = last.parent.parent;
            boolean pIsLeft = false;
            if(lpParent != null ) {
                pIsLeft = isLeft(last.parent);
            }

            last.parent.parent = last;
            last.parent.left = last.right;
            if(last.right != null) {
                last.right.parent = last.parent;
            }

            last.right = last.parent;
            last.parent = lpParent;

            if(lpParent == null ) {
                root = last;
            } else {
                if(pIsLeft) {
                    lpParent.left = last;
                } else {
                    lpParent.right = last;
                }
            }
        }

        // 左旋转last结点
        private void leftRotate(Node last) {
            Node lpParent = last.parent.parent;
            boolean pIsLeft = false;
            if(lpParent != null ) {
                pIsLeft = isLeft(last.parent);
            }

            last.parent.parent = last;
            last.parent.right = last.left;
            if(last.left != null) {
                last.left.parent = last.parent;
            }

            last.left = last.parent;
            last.parent = lpParent;

            if(lpParent == null ) {
                root = last;
            } else {
                if(pIsLeft) {
                    lpParent.left = last;
                } else {
                    lpParent.right = last;
                }
            }
        }

        // 获取整棵树的最大深度
        public int getMaxDepth() {
            return getMaxDepth(root, 0);
        }

        // assistMethod
        private int getMaxDepth(Node node, int depth) {
            if(node == null) {
                return depth;
            }

            int maxLeft = -1, maxRight = -1;
            if(node.left != null) {
                maxLeft = getMaxDepth(node.left, depth+1);
            } else {
                maxLeft = depth;
            }
            if(node.right != null) {
                maxRight = getMaxDepth(node.right, depth+1);
            } else {
                maxLeft = depth;
            } 

            return Tools.getMax(maxLeft, maxRight);
        }

        // 判断 node结点是否是叶子结点
        public boolean isLeaf(Node node) {
            return node.left == null && node.right == null;
        }

        // 判断 node结点是否是其父节点的左孩子
        public boolean isLeft(Node node) {
            return node == node.parent.left;
        }

        // 判断 node结点是否是其父节点的右孩子
        public boolean isRight(Node node) {
            return node == node.parent.right;
        }

        // 获取 node结点的兄弟结点
        public Node getUncle(Node node) {
            if(node.parent == null) {
                return null;
            }

            return node == node.parent.left ? node.parent.right : node.parent.left;
        }

        // 中序遍历  获取node的子树的字符串表示[得到的是一个有序序列]  存于sb中
        public void headFirstForString(Node node, StringBuilder sb) {
            if(node == null) {
                sb.append("null");
            } else {
                if(node.left != null) {
                    headFirstForString(node.left, sb);
                }
                sb.append(node.val + " color: " + node.getColor() + " ; ");
//              sb.append(node.val + " ");
                if(node.right != null) {
                    headFirstForString(node.right, sb);
                }
            }
        }

        // Debug
        public String toString() {
            StringBuilder sb = new StringBuilder();
            headFirstForString(root, sb);
            return sb.toString();
        }

    }

    // Node
    static class Node {
        // red, black的字符串表示
        // red, black的颜色表示
        private static final String RED_STR = "red";
        private static final String BLACK_STR = "black";
        private static final boolean RED = true;
        private static final boolean BLACK = false;

        // val 表示数据, parent表示该节点的父节点, isRed表示是否是红色
        // left, right 表示该节点的左孩子, 右孩子
        int val;
        boolean isRed;
        Node parent;
        Node left, right;

        // 初始化
        public Node() {
            isRed = RED;
        }

        public Node(Node parent, int val) {
            this();
            set(parent, null, null, val);
        }

        public Node(Node parent, Node left, Node right, int val) {
            this();
            set(parent, left, right, val);
        }

        public Node(Node other) {
            this.isRed = other.isRed;
            set(other.parent, other.left, other.right, other.val);
        }

        // setter
        public void set(Node parent, Node left, Node right, int val) {
            this.val = val;
            this.parent = parent;
            this.left = left;
            this.right = right;
        }

        // 当前结点是否是红色
        public boolean isRed() {
            return isRed;
        }

        // 当前结点是否是黑色
        public boolean isBlack() {
            return !isRed;
        }

        // 更新当前结点的颜色
        public void setColor(boolean isRed) {
            this.isRed = isRed;
        }

        // 更新其颜色 为其他颜色 (红 -> 黑), (黑 -> 红)
        public void transColor() {
            isRed = !isRed;
        }

        // 获取当前结点的颜色字符串表示
        private String getColor() {
            if(isRed) {
                return RED_STR;
            } else {
                return BLACK_STR;
            }
        }

        // Debug
        public String toString() {
            return "val : " + val + "  color : " + getColor();
        }

    }

}

效果截图

06 RedBlackTree_父节点

参考
[算法,红黑树] –2015.06.01
[红黑树 非常好]
[红黑树]