Java implementation Red-black tree

Source: Internet
Author: User
Tags comparable truncated

transferred from: http://www.cnblogs.com/skywang12345/p/3624343.html introduction of red and black trees

Red and Black (Red-black tree, abbreviated as R-b tree), a special two-fork search tree.
The red and black tree is a special two-fork search tree, which means it satisfies the characteristics of a binary search tree: Any node contains a key value greater than or equal to the left child's key value, less than or equal to the right child's key value.
In addition to this feature, the red-black tree also includes many additional information.

Each node of the red-black tree has a storage bit that represents the color of the node, which is either red (red) or black.
Characteristics of red and black trees:
(1) Each node is either black or red.
(2) The root node is black.
(3) Each leaf node is black. [Note: Here the leaf node, refers to the empty leaf node! ]
(4) If a node is red, its child nodes must be black.
(5) The same number of black nodes are included on all paths from one node to the descendant nodes of the node.

Regarding its characteristics, it is important to note that:
First, the leaf node in the feature (3) is a node that is only empty (nil or null).
Second, the feature (5) ensures that no path will be two times longer than the other path. Thus, the red-black tree is relatively close to the balance of the two-fork tree.

The red and black trees are as follows:

Java implementations of red and black Trees (code description)

The basic operation of the red-black tree is to add , remove , and rotate . When you add or remove a red-black tree, the rotation method is used. Why is it? The truth is very simple, add or remove the red and black tree nodes, the red and black trees have changed, may not meet the red and black tree 5 properties, it is no longer a red black tree, but an ordinary tree. By rotating it, you can make the tree a red-black tree again. To put it simply, the purpose of rotation is to keep the tree characteristic of the red and black trees.
The rotation consists of two types: Left and right . The following is a description of the basic operation of the red and black trees respectively.

1. Basic definition

public class Rbtree<t extends comparable<t>> {    private rbtnode<t> mroot;    Root node    private static Final Boolean RED   = false;    Private static Final Boolean BLACK = true;    public class Rbtnode<t extends Comparable<t>> {        Boolean color;        Color        T key;                Keyword (key value)        rbtnode<t> left;    Left child        rbtnode<t> right;    Right child        rbtnode<t> parent;    Parent node Public        rbtnode (T key, Boolean color, rbtnode<t> parent, rbtnode<t> left, rbtnode<t> right) {            This.key = key;            This.color = color;            This.parent = parent;            This.left = left;            This.right = right;        }    }    ...}

Rbtree is the class of the red-black tree, and Rbtnode is the node class of the red-black tree. The rbtree contains the associated APIs for the root node mroot and the red-black tree.
Note: During the implementation of the red-black tree API, I have overloaded many functions. The reason for overloading, one is that some APIs are internal interfaces, there are external interfaces, and the second is to make the structure clearer.

2. Left-handed

A left-hand spin on X means "turn X into a left node".

L-Left implementation code (Java language)

/* * Left rotation of the node (x) of the Red and black tree * * L (left-handed to Node X): * px px *//           * x Y */\-(left-handed)-.                     /\ # * LX y x ry */\/* ly ry LX ly * * */private void Leftrotate (rbtnode<t> x) {//Set X right child for y rbtnode<t> y = X.rig    Ht    Set "Y's left child" to "right child of X";//if the left child of Y is not empty, set "X" to "Y's father of the left child" x.right = Y.left;    if (y.left! = null) y.left.parent = x;    Set "Father of X" to "Father of y" y.parent = x.parent;            if (x.parent = = null) {this.mroot = y;    If "X's father" is an empty node, set Y to the root node} else {if (X.parent.left = = x) X.parent.left = y;    If X is the left child of its parent, set Y to "left child of the parent of x" Else x.parent.right = y;    If X is the left child of its parent node, set Y to "left child of Parent of X"}//Set "X" to "Y's Left child" y.left = x; Set "X's parent node" to "Y" x.parent = y;} 

3. Right-handed

A left-hand rotation of y means "turn y into a right node".

Right-handed implementation code (Java language)

/* * Right rotation of the node (y) of the Red and black tree * * Right (left-handed to Node Y): * py py */            /* y x */\--(right-handed)-.                                   /\ # * x ry lx y */\ /\ # * LX Rx rx ry * */private void Rightrotate (RBTNODE&LT;T&G T    Y) {//set X is the left child of the current node.    rbtnode<t> x = y.left;    Set "X's right Child" to "Y's left Child" and//if "X's right child" is not empty, set "Y" to "X's right child's father" Y.left = X.right;    if (x.right! = null) X.right.parent = y;    Set "Father of Y" to "Father of X" x.parent = y.parent;            if (y.parent = = null) {this.mroot = x;    If "Y's father" is an empty node, set X to the root node} else {if (y = = y.parent.right) y.parent.right = x;    If Y is the right child of its parent node, set X to "right child of parent node of y" Else y.parent.left = x; (Y is the left child of its parent node) set X to "The left child of the parent node of X "}//Sets" Y "to" X's right child "x.right = y; Set "Y's parent Node" to "x" y.parent = x;}

4. Add

What steps do you need to take to insert a node into a red-black tree? First, the red-black tree is treated as a binary lookup tree, the nodes are inserted, then the nodes are colored red, and finally, a series of actions such as "rotate and recolor" are used to correct the tree, making it a red-black tree again. Detailed descriptions are as follows:
The first step: the Red and black tree as a binary search tree, the node inserted.
The red and black tree itself is a binary search tree, after inserting the node, the tree is still a binary search tree. It also means that the key value of the tree is still orderly. In addition, whether it is left or right, if the tree is a two-fork search tree before rotation, it must still be a two-fork search tree after rotation. This also means that any rotation and recolor operation will not change the fact that it is still a binary search tree.
All right? Then we'll try to spin and recolor the tree and make it a red-black tree again!

Step Two: Colorize the inserted node as "red".
Why is it colored red instead of black? Why is it? Before answering, we need to review the features of the red and black trees:
(1) Each node is either black or red.
(2) The root node is black.
(3) Each leaf node is black. [Note: Here the leaf node, refers to the empty leaf node! ]
(4) If a node is red, its child nodes must be black.
(5) The same number of black nodes are included on all paths from one node to the descendant nodes of the node.
The inserted node is colored red and does not violate the "feature (5)"! The less you violate one trait, the less we need to deal with. Next, it is necessary to make the tree satisfy other properties, and if it is satisfied, it will be a red and black tree. O (∩∩) o ... Ha ha

The third step: through a series of rotation or coloring and so on, so that it becomes a red black tree.
In the second step, after the insertion node is shaded as "red", it does not violate "attribute (5)". So what exactly does it violate?
For "feature (1)", it is clear that it will not be violated. Because we've painted it red.
For "feature (2)", it is clear that it will not be violated. In the first step, we'll look at the red and black tree as a binary lookup tree and then perform the insert operation. The insert operation does not change the root node, depending on the characteristics of the binary lookup number. Therefore, the root node is still black.
For "feature (3)", it is clear that it will not be violated. The leaf nodes here refer to the empty leaf nodes, which are not affected by inserting non-empty nodes.
For "feature (4)", it is possible to violate!
Then, to find a way to "satisfy the trait (4)", we can reconstruct the tree into a red-black tree.


Add implementation code for the operation (Java language)

/  * * INSERT nodes into the red and black tree * * Parameter Description: * node     inserted node        //corresponds to node */private void Insert (rbtnode<t> node) in "Introduction to Algorithms" {in    T CMP;    Rbtnode<t> y = null;    rbtnode<t> x = this.mroot;    1. Use the red-black tree as a binary lookup tree, adding nodes to the two-fork lookup tree.    while (x = null) {        y = x;        CMP = Node.key.compareTo (x.key);        if (CMP < 0)            x = x.left;        else            x = x.right;    }    Node.parent = y;    if (y!=null) {        cmp = node.key.compareTo (y.key);        if (CMP < 0)            y.left = node;        else            y.right = node;    } else {        this.mroot = node;    }    2. Set the color of the node to red    node.color = red;    3. Re-fix it to a binary lookup tree    insertfixup (node);}  /* Create a new node (key) and insert it into the red black tree * * Parameter description: *     key insertion node */public void Insert (T key) {    rbtnode<t> node=new R Btnode<t> (key,black,null,null,null);    If the new node fails, it is returned.    if (node! = null)        Insert (node);}

The internal interface --The role of Insert (node) is to insert the nodes into a red-black tree.
The external interface -Insert (key) is the function of adding "key" to the red-black tree.


Add implementation code for remediation actions (Java language)

/* * Red black Tree Insert correction function * * After inserting a node into a red black tree (out of balance), call the function again; * The aim is to reshape it into a red and black tree. * * Parameter Description: * node inserted node//corresponding to "Introduction to the algorithm" Z */private void Insertfixup (rbtnode<t> node) {rbtnode<t> P    Arent, gparent; If the parent node exists and the parent node's color is red while (((Parent = parentof (node))!=null) && isred (parent)) {gparent = Parentof (        Parent); If the "Parent node" is the "left child of the grandparent node" if (parent = = Gparent.left) {//Case 1 Condition: Uncle node is red rbtnode<t> uncle            = Gparent.right;                if ((uncle!=null) && isred (uncle)) {setblack (uncle);                Setblack (parent);                Setred (gparent);                node = gparent;            Continue                }//Case 2 condition: Uncle is black, and the current node is right child if (parent.right = = node) {rbtnode<t> tmp;                Leftrotate (parent);                TMP = parent;                parent = node;            node = tmp;       }//Case 3 condition: Uncle is black, and the current node is the left child.     Setblack (parent);            Setred (gparent);        Rightrotate (gparent);            } else {//if "Z's parent node" is "Z's grandfather Node right child"//Case 1 Condition: Uncle node is red rbtnode<t> uncle = Gparent.left;                if ((uncle!=null) && isred (uncle)) {setblack (uncle);                Setblack (parent);                Setred (gparent);                node = gparent;            Continue                }//Case 2 condition: Uncle is black, and the current node is left child if (Parent.left = = node) {rbtnode<t> tmp;                Rightrotate (parent);                TMP = parent;                parent = node;            node = tmp;            }//Case 3 condition: Uncle is black, and the current node is the right child.            Setblack (parent);            Setred (gparent);        Leftrotate (gparent); }}//Set the root node to black Setblack (this.mroot);}

Insertfixup (node) corresponds to "the third step mentioned above". It is an internal interface.

5. Delete operation

Delete one of the nodes in the red and black tree. The actions that need to be performed are: first, the red-black tree is treated as a binary lookup tree, and the node is removed from the two-fork lookup tree, and then the tree is corrected by a series of "rotation and recolor" to make it a red-black tree again. Detailed descriptions are as follows:
The first step: the Red and black tree as a binary search tree, the node is deleted.
This is the same as deleting a node in a regular binary lookup tree. In 3 different situations:
① deleted node No son, that is, leaf node. Then, deleting the node directly will be OK.
② is deleted node only one son. Then, delete the node directly and replace its location with the node's unique child node.
③ deleted node has two sons. Then, identify its successor, and then copy the contents of its successor to the content of that node, and then delete its successor. Here, the successor node is equivalent to the alias, after the contents of the successor node are copied to the "Deleted node", then the successor node is deleted. This subtly transforms the problem into a "delete successor" scenario, and the following is considered for subsequent nodes. In the case of a "deleted node" with two non-empty-space nodes, its successor cannot be a Gemini non-null. Since the "successor" cannot be null and void, it means that "the node's successor" either has no son or only one son. If there is no son, the "situation ①" to deal with, if only one son, according to "situation ②" to deal with.

Step two: Fix the tree with a series of "rotation and re-coloring" to make it a red-black tree again.
Because the node is deleted in the first step, it may violate the characteristics of the red-black tree. Therefore, the tree needs to be corrected by "rotation and re-coloring" to make it a red-black tree again.

Implementation code for the delete operation (Java language)

/* Delete node (node) and return deleted node * parameter description: * node deleted node */private void Remove (rbtnode<t> node) {rbtnode<t> C    Hild, parent;    Boolean color;    The "left and right children are not empty" situation of the deleted node. if ((node.left!=null) && (node.right!=null)) {//The subsequent node of the truncated point.        (called a "replacement node")//use it to replace the "truncated" position and then remove the "truncated point".        rbtnode<t> Replace = node;        Get successor Node replace = Replace.right;        while (replace.left! = null) replace = Replace.left;                "Node" is not the root node (only the root node does not have a parent node) if (Parentof (node)!=null) {if (Parentof (node). left = = node)            Parentof (node). left = replace;        else Parentof (node). right = replace;            The else {//' node nodes ' is the root node, updating the root node.        This.mroot = replace;        }//Child is the right kid for "replace node" and also the "node to adjust". "Replacement node" certainly does not exist left child!        Because it is a successor node.        Child = Replace.right;        Parent = Parentof (replace);        Save "Replace node" color = colorof (replace); The deleted sectionThe point "is" the parent node of its successor "if (parent = = node) {parent = replace;            } else {//child is not NULL if (child!=null) 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 = = BLACK) Removefixup (child, parent);        node = null;    return;    } if (Node.left!=null) {child = Node.left;    } else {child = Node.right;    } parent = Node.parent;    Save "Replace node" color = Node.color;    if (child!=null) child.parent = parent;        "Node" is not the root node if (parent!=null) {if (Parent.left = = node) Parent.left = child;    else parent.right = child;    } else {this.mroot = child; } if (color = = BLACK) removefixUp (child, parent); node = null;}      /* Delete node (z) and return deleted node * * Parameter Description: * Root node of tree red black tree * z Delete node */public void remove (T key) {rbtnode<t> node; if (node = search (Mroot, key)) = null) remove (node);

The internal interface -the function of Remove (node)-is to insert the nodes into the red-black tree.
external Interface -Remove (key) removes the node in the red-black tree with the key value.


Remove implementation code for remediation actions (Java language)

/* * Red black Tree Delete correction function * * After removing the insertion node from the red black tree (the red black tree loses its balance), call the function again; * The aim is to reshape it into a red-black tree. * * Parameter Description: * node to be fixed */private void Removefixup (rbtnode<t> node, rbtnode<t> parent) {RBTNODE&LT;T&G T    Other;  while ((Node==null | | isblack (node)) && (node! = this.mroot)) {if (Parent.left = = node) {Other            = Parent.right;                if (isred (other)) {//1:x brother W is Red Setblack (other);                setred (parent);                Leftrotate (parent);            other = Parent.right; } if ((Other.left==null | | isblack (OTHER.LEFT)) && (Other.right==null | | isblack (OTHER.R                ight)) {//Case 2:x's brother W is black, and both children of W are Black setred (other);                node = parent;            Parent = parentof (node); } else {if (Other.right==null | | isblack (other.right)) {//Case 3:x Brother W is black, and W's left child is red                Color, the right child is black.      Setblack (Other.left);                    Setred (other);                    Rightrotate (other);                other = Parent.right;                }//Case 4:x's brother W is black, and the right child of W is red, left child any color.                SetColor (Other, colorof (parent));                Setblack (parent);                Setblack (Other.right);                Leftrotate (parent);                node = this.mroot;            Break            }} else {other = Parent.left;                if (isred (other)) {//1:x brother W is Red Setblack (other);                setred (parent);                Rightrotate (parent);            other = Parent.left; } if ((Other.left==null | | isblack (OTHER.LEFT)) && (Other.right==null | | isblack (OTHER.R                ight)) {//Case 2:x's brother W is black, and both children of W are Black setred (other);                node = parent;            Parent = parentof (node); } ELSE {if (Other.left==null | | isblack (OTHER.LEFT)) {//Case 3:x Brother W is black, and W's left child is red, right child                      is black.                    Setblack (Other.right);                    Setred (other);                    Leftrotate (other);                other = Parent.left;                }//Case 4:x's brother W is black, and the right child of W is red, left child any color.                SetColor (Other, colorof (parent));                Setblack (parent);                Setblack (Other.left);                Rightrotate (parent);                node = this.mroot;            Break }}} if (Node!=null) setblack (node);}

Removefixup (node, parent) corresponds to "the third step mentioned above". It is an internal interface.

Java implementation of red and black tree (full source)

The following is the complete code implemented by the red and black tree and the corresponding test program.
(1) In addition to the above-mentioned "left", "right", "add", "delete" and other basic operations, but also implemented the "traverse", "find", "print", "minimum", "Maximum", "create", "destroy" and other interfaces.
(2) The function interface is mostly divided into internal interface and external interface. The internal interface is the private function, and the external interface is the public function.
(3) The detection switch of "insert" and "delete" action is provided in the test code. The default is off, and the Open method can refer to "instructions in code". It is recommended that you draw a red-black tree on the draft after you turn on the switch.

Implementation files for red and black trees (Rbtree.java)

View Code

Test file for red and black trees (Rbtreetest.java)

View Code

Red and Black Tree Java test program

The red and Black tree's test code (RBTREETEST.JAVA) has been given earlier and is not repeated here. Here is the result of the test program running:

= = Raw DATA: 10 40 30 60 90 70 20 50 80 = = pre-sequence traversal: 30 10 20 60 40 50 80 70 90 = = Sequence Traversal: 10 20 30 40 50 60 70 80 90 = post-order traversal: 20 10 50 40 70 90 80 60 30 = = Min.: 10== Max: 90== tree Details: (b) is root10 (b) is a and left   CHILD20 (R) is ' s right  chil D60 (R) is a ' s right child40 (b) is a ' s left   CHILD50 (R) is a + ' s right  Child80 (b) is a "s" Right  Child70 (R) Is the left   child90 (R) is the S  

Java implementation Red-black tree

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.