Detailed set of Java 6: This time, start to finish with your interpretation of Java in the red-black tree

"Detailed set of Java Series" after I finished tamp Java Basics series of blog ready to start writing a new series.

These articles will arrange to me on GitHub's "Java Interview Guide" warehouse, more exciting content please go to my warehouse View

https://github.com/h2pl/Java-Tutorial

Like it under the trouble spots Star, fork Kazakhstan

Article first appeared in my personal blog:

www.how2playlife.com

What is the red-black tree

First, what is the red-black trees? Red-black tree is a "balanced" binary search tree, which is a classical efficient algorithm, to ensure that the worst case time dynamic set of operations is O (lgn). Each red-black tree node contains five fields, respectively, color, key, left, right, and p. increase in color is the color on each node indicates a storage node, or may be RED BLACK. values ​​for the key value in the node, left, right left and right child nodes for the pointer, it is not NIL, p is a pointer pointing to a section of the parent node. FIG follows (Wikipedia) is represented by a red-black tree, NIL is a pointer pointing to the node outside. (Extranodal point as a node is not the key)

       What red-black tree in nature? Commonly referred to as red, black and nature, the following five points:

     1) Each node is either red or black;

     2) the root node is black;

     3) Each leaf node (NIL) is black;

     4) If a node is red, then its two children are black;

     5) for each node, it contains the same number of black nodes on all paths from the node to other nodes of its descendants.

       For the latter analysis, we have to know the following knowledge points.

    (1) Black height: from a node x (the node is not included) onto any one of a path-leaf node, black node number of the node called a black height x.

    (2) there is a red-black tree of n nodes within a height up to 2lg (n + 1). (Nodal point as a red-black tree nodes with keywords)

    (3) an internal node comprising n-black tree height is O (log (n)).

definition

Special red-black tree is a binary search tree, also known as RB trees (RED-BLACK-TREE), since the special red-black tree is a binary search tree, i.e., a red-black tree having a binary search tree features, and red black tree has the following features:

  • 1. Each node is either black or red

  • 2. The root is black

  • 3. Each leaf node is black, and the node is empty (there is another way of saying that, with each leaf node are two empty black node (referred Whistle soldiers), if a node n only one child left, then the right child n Whistle is a soldier; if the node n only a right child, then the child is left n Whistle a soldier).

  • 4. If a node is red, its child nodes must be black

  • 5. from one node to all descendants of the node node path comprising the same number of black nodes.

There are several points to note are:

1. The characteristics of each leaf node specified in red-black tree node 3 are empty, but in Java to achieve red-black tree will use null behalf empty node can not see a black leaf node is therefore red-black tree traversal, but see the leaf node is red

2. Features 4 to ensure the longest path from the root node of the leaf node is no more than twice the length of any other path, for example, a height of the black red-black tree 3, the shortest path (path is the root node to the leaf node) 2 (black node - node black - black nodes), which is the longest path 4 (black node - node red - black node - node red - black nodes).

practice

Red-black tree operations

Insert

First, red-black tree node during insertion, we set the color of the insert node is red , if the inserted node is black, 5 bound contrary characteristics, i.e., changing the height of the black red-black tree, following the insertion node and the presence of red the situations:

1. Black Father

As shown, this does not destroy the characteristic red-black tree, i.e. without any treatment

Detailed set of Java 6: This time, start to finish with your interpretation of Java in the red-black tree

2. Red father

When his father will be red following cases

  • Red t

Red t where, in fact, relatively simple, as shown, only by modifying the parent, tertiary color is black, the color is red ancestors, and go back to recursively check node ancestor

Detailed set of Java 6: This time, start to finish with your interpretation of Java in the red-black tree

  • Black t

Black tert case are summarized as follows, under some circumstances it is not able to modify the color by the effect of equilibrium, and therefore by the rotating operation, two kinds of red and black species doubt rotating operation, left and right (now exists when to use the left-hand, right-handed use what time)

  • Case 1: [First dextrose, changing the color (black root node must, for the two child nodes of its red, without changing node t)], as shown below, the node will be omitted noted the soldiers Whistle

Detailed set of Java 6: This time, start to finish with your interpretation of Java in the red-black tree

  • Case 2: [Case1 first case into the left and then the right-handed, the final color change (the root node must be black and its two child nodes is red, the node without changing t)], as shown below, attention will be omitted Whistle soldiers node

Detailed set of Java 6: This time, start to finish with your interpretation of Java in the red-black tree

  • Case 3: [L first, and finally change the color (black root node must, for the two child nodes of its red, without changing node t)], as shown below, the node will be omitted noted the soldiers Whistle

Detailed set of Java 6: This time, start to finish with your interpretation of Java in the red-black tree

  • Case 4: [Case 3 where the first into the right-hand, left-handed and then, the final color change (the root node must be black and its two child nodes is red, the node without changing t)], as shown below, attention will be omitted Whistle soldiers node

Detailed set of Java 6: This time, start to finish with your interpretation of Java in the red-black tree

These are the new red-black tree node all possible actions, will be introduced following the deletion of the red-black tree

Deletion

Deletion compared to a more complicated operation of inserting, deleting a node can be roughly divided into three cases:

  • 1. Remove the child node is not the node that the current node is a leaf node, which can be deleted directly

  • 2. Delete the node has a child node, this need to delete the current node and its child nodes using replacement up

  • 3. Delete node has two children nodes, which need to find its successor nodes (larger than the smallest element in the tree node); then copy the contents of its successor node to the node, which is equivalent to the successor node substitute node, it should be noted that the successor node will not have two children nodes (this point should be well understood, if the subsequent node has a left child node, the current node's successor certainly not least, one can only explain successor node no child node exists, or only a right child node), i.e., so that the problem will be converted into 1 in such a manner.

Prior to about a repair operation, you first need to understand a few,

1. For the red-black tree, where a single branch node just as the case shown in FIG, black is the current node, the child node which is red, (1 Assuming the current node is red, its two children node must be black, 2. if grandson node, it certainly is black, resulting in varying amounts of sunspots, and red-black tree unbalanced)

Detailed set of Java 6: This time, start to finish with your interpretation of Java in the red-black tree

2.由于红黑树是特殊的二叉查找树,它的删除和二叉查找树类型,真正的删除点即为删除点A的中序遍历的后继(前继也可以),通过红黑树的特性可知这个后继必然最多只能有一个孩子,其这个孩子节点必然是右孩子节点,从而为单支情况(即这个后继节点只能有一个红色孩子或没有孩子)

下面将详细介绍,在执行删除节点操作之后,将通过修复操作使得红黑树达到平衡的情况。

  • Case 1:被删除的节点为红色,则这节点必定为叶子节点(首先这里的被删除的节点指的是真正删除的节点,通过上文得知的真正删除的节点要么是节点本身,要么是其后继节点,若是节点本身则必须为叶子节点,不为叶子节点的话其会有左右孩子,则真正删除的是其右孩子树上的最小值,若是后继节点,也必须为叶子节点,若不是则其也会有左右孩子,从而和2中相违背),这种情况下删除红色叶节点就可以了,不用进行其他的操作了。

Detailed set of Java 6: This time, start to finish with your interpretation of Java in the red-black tree

  • Case 2:被删除的节点是黑色,其子节点是红色,将其子节点顶替上来并改变其颜色为黑色,如下图所示

Detailed set of Java 6: This time, start to finish with your interpretation of Java in the red-black tree

  • Case 3:被删除的节点是黑色,其子节点也是黑色,将其子节点顶替上来,变成了双黑的问题,此时有以下情况

    • Case 1:新节点的兄弟节点为红色,此时若新节点在左边则做左旋操作,否则做右旋操作,之后再将其父节点颜色改变为红色,兄弟节点

Detailed set of Java 6: This time, start to finish with your interpretation of Java in the red-black tree

Detailed set of Java 6: This time, start to finish with your interpretation of Java in the red-black tree

从图中可以看出,操作之后红黑树并未达到平衡状态,而是变成的黑兄的情况

  • Case 2:新节点的兄弟节点为黑色,此时可能有如下情况

    • 红父二黑侄:将父节点变成黑色,兄弟节点变成红色,新节点变成黑色即可,如下图所示

Detailed set of Java 6: This time, start to finish with your interpretation of Java in the red-black tree

Detailed set of Java 6: This time, start to finish with your interpretation of Java in the red-black tree

  • 黑父二黑侄:将父节点变成新节点的颜色,新节点变成黑色,兄弟节点染成红色,还需要继续以父节点为判定点继续判断,如下图所示

Detailed set of Java 6: This time, start to finish with your interpretation of Java in the red-black tree

Detailed set of Java 6: This time, start to finish with your interpretation of Java in the red-black tree

  • 红侄:

Where a: the new node at a right subtree, red nephew in the sibling nodes left subtree, the operation at this time is right-handed, and the sibling node becomes the father of the color, to black parent node, the node becomes a nephew black, as follows FIG.

Detailed set of Java 6: This time, start to finish with your interpretation of Java in the red-black tree

Case 2: the new node in the right subtree, nephew in the sibling nodes red right subtree, the operation at this time for the first left, the right-handed and nephew node becomes the father of the color, the parent node becomes black, as shown in FIG.

Detailed set of Java 6: This time, start to finish with your interpretation of Java in the red-black tree

Three cases: a new node in the left subtree, red nephew left sibling subtree, this time for the first operation in the left-handed and right-handed nephew node becomes the father of the color, to black parent node, as shown in FIG.

Detailed set of Java 6: This time, start to finish with your interpretation of Java in the red-black tree

Four cases: the new node in the right subtree, right subtree red nephew sibling nodes, in this case left-handed operation, and to a color sibling node of the parent node becomes the parent node black, nephew node becomes black, the following FIG.

Detailed set of Java 6: This time, start to finish with your interpretation of Java in the red-black tree

Red-black tree implementation

It is implemented using the JAVA code as red-black tree processes, including insert, delete, L, D, traversal operation

insert
/* 插入一个节点
 * @param node
 */
private void insert(RBTreeNode<T> node){
    int cmp;
    RBTreeNode<T> root = this.rootNode;
    RBTreeNode<T> parent = null;

    //定位节点添加到哪个父节点下
    while(null != root){
        parent = root;
        cmp = node.key.compareTo(root.key);
        if (cmp < 0){
            root = root.left;
        } else {
            root = root.right;
        }
    }

    node.parent = parent;
    //表示当前没一个节点,那么就当新增的节点为根节点
    if (null == parent){
        this.rootNode = node;
    } else {
        //找出在当前父节点下新增节点的位置
        cmp = node.key.compareTo(parent.key);
        if (cmp < 0){
            parent.left = node;
        } else {
            parent.right = node;
        }
    }

    //设置插入节点的颜色为红色
    node.color = COLOR_RED;

    //修正为红黑树
    insertFixUp(node);
}

/**
 * 红黑树插入修正
 * @param node
 */
private void insertFixUp(RBTreeNode<T> node){
    RBTreeNode<T> parent,gparent;
    //节点的父节点存在并且为红色
    while( ((parent = getParent(node)) != null) && isRed(parent)){
        gparent = getParent(parent);

        //如果其祖父节点是空怎么处理
        // 若父节点是祖父节点的左孩子
        if(parent == gparent.left){
            RBTreeNode<T> uncle = gparent.right;
            if ((null != uncle) && isRed(uncle)){
                setColorBlack(uncle);
                setColorBlack(parent);
                setColorRed(gparent);
                node = gparent;
                continue;
            }

            if (parent.right == node){
                RBTreeNode<T> tmp;
                leftRotate(parent);
                tmp = parent;
                parent = node;
                node = tmp;
            }

            setColorBlack(parent);
            setColorRed(gparent);
            rightRotate(gparent);
        } else {
            RBTreeNode<T> uncle = gparent.left;
            if ((null != uncle) && isRed(uncle)){
                setColorBlack(uncle);
                setColorBlack(parent);
                setColorRed(gparent);
                node = gparent;
                continue;
            }

            if (parent.left == node){
                RBTreeNode<T> tmp;
                rightRotate(parent);
                tmp = parent;
                parent = node;
                node = tmp;
            }

            setColorBlack(parent);
            setColorRed(gparent);
            leftRotate(gparent);
        }
    }
    setColorBlack(this.rootNode);
}

Operation of inserting the node in the following steps:

  • 1. Location: the finishing red-black tree traversal, determining the position of addition, the code positions as the insert method is found in the added

  • 2. Repair: This is described in the foregoing, the additive element may be red-black tree that does not meet the characteristics thereof, by which color when needed, to adjust the rotation of red-black tree, i.e. code above method insertFixUp
Delete Node

The following code to delete nodes

private void remove(RBTreeNode<T> node){
    RBTreeNode<T> child,parent;
    boolean color;
    //被删除节点左右孩子都不为空的情况
    if ((null != node.left) && (null != node.right)){

        //获取到被删除节点的后继节点
        RBTreeNode<T> replace = node;

        replace = replace.right;
        while(null != replace.left){
            replace = replace.left;
        }

        //node节点不是根节点
        if (null != getParent(node)){
            //node是左节点
            if (getParent(node).left == node){
                getParent(node).left = replace;
            } else {
                getParent(node).right = replace;
            }
        } else {
            this.rootNode = replace;
        }

        child = replace.right;
        parent = getParent(replace);
        color = getColor(replace);

        if (parent == node){
            parent = replace;
        } else {
            if (null != child){
                setParent(child,parent);
            }
            parent.left = child;

            replace.right = node.right;
            setParent(node.right, replace);
        }

        replace.parent = node.parent;
        replace.color = node.color;
        replace.left = node.left;
        node.left.parent = replace;
        if (color == COLOR_BLACK){
            removeFixUp(child,parent);
        }

        node = null;
        return;
    }

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

    parent = node.parent;
    color = node.color;
    if (null != child){
        child.parent = parent;
    }

    if (null != parent){
        if (parent.left == node){
            parent.left = child;
        } else {
            parent.right = child;
        }
    } else {
        this.rootNode = child;
    }

    if (color == COLOR_BLACK){
        removeFixUp(child, parent);
    }
    node = null;
}
/**
 * 删除修复
 * @param node
 * @param parent
 */
private void removeFixUp(RBTreeNode<T> node, RBTreeNode<T> parent){
    RBTreeNode<T> other;
    //node不为空且为黑色,并且不为根节点
    while ((null == node || isBlack(node)) && (node != this.rootNode) ){
        //node是父节点的左孩子
        if (node == parent.left){
            //获取到其右孩子
            other = parent.right;
            //node节点的兄弟节点是红色
            if (isRed(other)){
                setColorBlack(other);
                setColorRed(parent);
                leftRotate(parent);
                other = parent.right;
            }

            //node节点的兄弟节点是黑色,且兄弟节点的两个孩子节点也是黑色
            if ((other.left == null || isBlack(other.left)) &&
                    (other.right == null || isBlack(other.right))){
                setColorRed(other);
                node = parent;
                parent = getParent(node);
            } else {
                //node节点的兄弟节点是黑色,且兄弟节点的右孩子是红色
                if (null == other.right || isBlack(other.right)){
                    setColorBlack(other.left);
                    setColorRed(other);
                    rightRotate(other);
                    other = parent.right;
                }
                //node节点的兄弟节点是黑色,且兄弟节点的右孩子是红色,左孩子是任意颜色
                setColor(other, getColor(parent));
                setColorBlack(parent);
                setColorBlack(other.right);
                leftRotate(parent);
                node = this.rootNode;
                break;
            }
        } else {
            other = parent.left;
            if (isRed(other)){
                setColorBlack(other);
                setColorRed(parent);
                rightRotate(parent);
                other = parent.left;
            }

            if ((null == other.left || isBlack(other.left)) &&
                    (null == other.right || isBlack(other.right))){
                setColorRed(other);
                node = parent;
                parent = getParent(node);
            } else {
                if (null == other.left || isBlack(other.left)){
                    setColorBlack(other.right);
                    setColorRed(other);
                    leftRotate(other);
                    other = parent.left;
                }

                setColor(other,getColor(parent));
                setColorBlack(parent);
                setColorBlack(other.left);
                rightRotate(parent);
                node = this.rootNode;
                break;
            }
        }
    }
    if (node!=null)
        setColorBlack(node);
}

To delete a node is divided into several situations to do the deal corresponds to:

  • 1. Remove node, according to the following three cases to remove a node
    • 1. actually delete the node has no children
    • 2. actually deleted node has a child node
    • 3. Removing node has two child nodes
  • 2. Fix red-black tree characteristics, such as calling removeFixUp method code fix red-black tree properties.

3. Summary

Above describes some of the characteristics of the red-black tree, including some detailed analysis of the operations inside the process of writing a long time, I feel really more difficult to reason clearly. Behind will continue to understand more deeply, where if there is a problem, please correct me.

Reference article

Red-black tree (v) implementation of Java

Achieved by analyzing the source code of JDK study red-black tree algorithm TreeMap

Red-black tree

Insert and Delete (graphic) of red-black tree

Red-black tree-depth analysis and Java implementation

Guess you like

Origin blog.51cto.com/14006572/2448598