Usage of the red/black tree

Source: Internet
Author: User

(The learning references are mainly introduction to algorithms.)

The first is the nature of the red and black trees. A binary search tree is a red-black tree that meets the following requirements.

1) each node is either red or black.

2) The root node is black.

3) each leaf node (NIL) is black.

4) The two children at the Red node are black.

5) for any node, all paths from it to its child node contain the same number of black nodes.

I don't care about it at the beginning, but I will know after studying the algorithms carefully that the algorithms focus on maintaining these properties. Nature 5) ensures high efficiency when using the red/black tree. The Theorem proves that the height of the red and black trees with n inner nodes is mostly 2lg (n + 1 ).

Different from the common Binary Search Tree, the red and black trees generally use a sentinel node to represent NIL, which provides a lot of convenience for the use of the algorithm. You can understand it when writing it. The Sentinel is set to black. It is the root parent node and all leaf nodes. Other fields can be set to any value. I use keywords to distinguish it from common nodes.

Rotation is a special operation of the red and black trees. In the past, I had no idea how the left-and right-handed operations were carried out. Now I know that, in this case, the left-and-right-handed operations on the x node can be summarized as follows, convert x from the root of a subtree to the left child of the subtree. symmetric, likewise. Rotation is an operation that can be performed to maintain the red/black nature during Tree insertion and deletion.

Insert principle:

Except for the processing of null pointers, the insertion process is the same as that of the Binary Search Tree. However, after insertion, a unique adjustment algorithm is required to ensure the color and black. The description below is my personal summary, which seems confusing and may be easier to understand than algorithms and instances.

The newly inserted vertex z is directly red, and then adjusted based on whether its parent node is red (in conflict with Nature 4) and whether the inserted node is root (in conflict with Nature 2. The latter can directly dye the root.

For the former, find Uncle y of z (although it is easy to find Uncle y, It is not detailed), and further differentiate the situation based on whether y is red or black. When z's father is a left child, the former only needs to blacklist the father and uncle of z at the same time, the father node of z becomes red, and z points to the parent node of z for iterative processing; the latter further divides z into the left or right children. Z is the first case when the left child is directly rotated by z's parent node so that z's father left and becomes the new z. In the latter case, the father of z is black, and his grandfather is red, and z's grandfather is right-handed.

Principles of deletion:

The deletion algorithm in the introduction to algorithms is very skillful to process both cases at the same time. In addition to determining whether to adjust the color of the deleted node, the deletion of the red/black tree is no different from that of the common Binary Search Tree. Here we will analyze it a little.

Copy codeThe Code is as follows: RB-DELETE (T, z) // case 1 | case 2
If left [z] = nil [T] or right [z] = nil [T] // z when there is at most one child | when z has two children
Then y ← z // make y = z | make y followed by z (at this time, y is not the right child of z)
Else y pair TREE-SUCCESSOR (z) // ================================================ ========================================================== =
If left [y] =nil [T] // the child or sentinel whose x is y | make x the right child of y (x is not the left child, otherwise, y cannot be the successor of z)
Then x left [y] // | x will replace y in the future
Else x release right [y] // ============================================== ========================================================== ==========
P [x] ← p [y] //
If p [y] = nil [T] //
Then root [T] between x // The relationship between x and x's new father
Else if y = left [p [y] //
Then left [p [y] returns x //
Else right [p [y] else x // ==================================== ========================================================== ==================
If y! = Z // |
Then key [z] primary key [y] // move up after deletion | alternative, used to delete the replaced original Node
Copy y's satellite data into z // |
If color [y] = BLACK // |
Then RB-DELETE-FIXUP (T, x) // |
Return y

After deletion, if the deleted node is black, it may cause a violation of nature 2, 4, and 5. The algorithm is adjusted to make the x that replaces y dye a black layer and become a red-Black or double-black node. This processing is only indicated by the pointer x, and does not change the content of the color field of the node. There are eight adjustment algorithms, two of which are symmetric and only four are described.

Use w to represent the brother of x.

Case 1 is w red. In this case, w is changed to black, p [x] is red, and p [x] is left-handed. w points to the new brother of x, which is the case of 2, 3, or 4.

Case 2 is Black w, and both children of w are black. In this case, w is red and p [x] becomes the new x. This is equivalent to removing x from the black layer, so that the black layer is moved up.

Case 3 is w black, w's left child is red, and the right child is black. In this case, the color of w and the left child is exchanged and w is right-handed. This is case 4.

In case 4, w is black and w is red. In this case, w becomes the color of p [x], p [x] is set to black, w's right child is set to black, and p [x] is left-handed. Make x the root. At this time, it is equivalent to passing a heavy black on x to his father and moving it down together, while w replaces his father's original color and position. This is because there are no red-black nodes or double-black nodes.

Each processing operation checks whether x is the root and whether x is black. When x is not the root and black, it indicates that there are red and black nodes or double black nodes. A new round of cycle is required. After the cycle ends, the root is dyed black.

Finally, I attached a red/black tree operation written in C. The insert operation is verified correctly. The number of delete operation verifications is limited, and a bug may exist.

Copy codeThe Code is as follows: # include <stdlib. h>
# Include <stdio. h>

# Define T_nil-1
// T_nil is a key of nil [T] in the book.
# Define RED 1
# Define BLACK 0 // T_nil is BLACK

// T_nil's p is itself. need to set.

Struct rb_tree {
Int color;
Int key; // normally a positive number.
Struct rb_tree * left;
Struct rb_tree * right;
Struct rb_tree * p;
};

Int rb_walk (struct rb_tree * node ){
If (node-> key! = T_nil ){
Rb_walk (node-> left );
Printf ("% d, color is % s \ n", node-> key, (node-> color? "RED": "BLACK "));
Rb_walk (node-> right );
}
Return 1;
}

Struct rb_tree * rb_search (struct rb_tree * node, int k ){
If (node-> key = T_nil) | (node-> key = k ))
Return node;

If (k <node-> key)
Return rb_search (node-> left, k );
Else
Return rb_search (node-> right, k );
}

Struct rb_tree * tree_minimum (struct rb_tree * node ){
If (node-> key = T_nil)
Return node;
While (node-> left-> key! = T_nil)
Node = node-> left;
Return node;
}

Struct rb_tree * tree_maximum (struct rb_tree * node ){
If (node-> key = T_nil)
Return node;
While (node-> right-> key! = T_nil)
Node = node-> right;
Return node;
}

Struct rb_tree * tree_successor (struct rb_tree * node ){
Struct rb_tree * y;
If (node-> right-> key! = T_nil)
Return tree_minimum (node-> right );
Y = node-> p;
While (y-> key! = T_nil) & (node = y-> right )){
Node = y;
Y = y-> p;
}
Return y;
}
// 3 function of below is copy from tree.

Struct rb_tree * left_rotate (struct rb_tree * rb, struct rb_tree * x ){
Struct rb_tree * y;
// If (x-> right-> key = T_nil ){
// Printf ("have no right child, rotation cancel. \ n ");
// Return rb;
//}
Y = x-> right;
X-> right = y-> left;
If (y-> left-> key! = T_nil)
Y-> left-> p = x;
Y-> p = x-> p;
If (x-> p-> key = T_nil)
Rb = y;
Else if (x = x-> p-> left)
X-> p-> left = y;
Else
X-> p-> right = y;
Y-> left = x;
X-> p = y;
Return rb;
}

Struct rb_tree * right_rotate (struct rb_tree * rb, struct rb_tree * x ){
Struct rb_tree * y;
// If (x-> left-> key = T_nil ){
// Printf ("have no left child, rotation cancel. \ n ");
// Return rb;
//}
Y = x-> left;
X-> left = y-> right;
If (y-> right-> key! = T_nil)
Y-> right-> p = x;
Y-> p = x-> p;
If (x-> p-> key = T_nil)
Rb = y;
Else if (x = x-> p-> left)
X-> p-> left = y;
Else
X-> p-> right = y;
Y-> right = x;
X-> p = y;
Return rb;
}

Struct rb_tree * rb_insert_fixup (struct rb_tree * rb, struct rb_tree * z ){
Struct rb_tree * y;
While (z-> p-> color = RED ){
If (z-> p = z-> p-> left ){
Y = z-> p-> right;
If (y-> color = RED ){
Z-> p-> color = BLACK;
Y-> color = BLACK;
Z-> p-> color = RED;
Z = z-> p;
}
Else {
If (z = z-> p-> right ){
Z = z-> p;
Rb = left_rotate (rb, z );
}
Z-> p-> color = BLACK;
Z-> p-> color = RED;
Rb = right_rotate (rb, z-> p );
}
}
Else {// same as right and left exchanged
Y = z-> p-> left;
If (y-> color = RED ){
Z-> p-> color = BLACK;
Y-> color = BLACK;
Z-> p-> color = RED;
Z = z-> p;
}
Else {
If (z = z-> p-> left ){
Z = z-> p;
Rb = right_rotate (rb, z );
}
Z-> p-> color = BLACK;
Z-> p-> color = RED;
Rb = left_rotate (rb, z-> p );
}
}
}
Rb-> color = BLACK;
Return rb;
}

Struct rb_tree * rb_insert (struct rb_tree * rb, int k ){
Struct rb_tree * y = rb-> p;
Struct rb_tree * x = rb;
Struct rb_tree * z;
Z = (struct rb_tree *) malloc (sizeof (struct rb_tree ));
Z-> key = k;
While (x-> key! = T_nil ){
Y = x;
If (k <x-> key)
X = x-> left;
Else
X = x-> right;
}
Z-> p = y;
If (y-> key = T_nil)
Rb = z;
Else if (z-> key <y-> key)
Y-> left = z;
Else
Y-> right = z;
Z-> left = rb-> p;
Z-> right = rb-> p;
Z-> color = RED;
Return rb_insert_fixup (rb, z );
}

Struct rb_tree * rb_delete_fixup (struct rb_tree * rb, struct rb_tree * x ){
Struct rb_tree * w;
While (x! = Rb) & (x-> color = BLACK )){
If (x = x-> p-> left ){
W = x-> p-> right;
If (w-> color = RED ){
W-> color = BLACK;
X-> p-> color = RED;
Left_rotate (rb, x-> p );
W = x-> p-> right;
}
If (w-> left-> color = BLACK) & (w-> right-> color = BLACK )){
W-> color = RED;
X = x-> p;
}
Else if (w-> right-> color = BLACK ){
W-> left-> color = BLACK;
W-> color = RED;
Right_rotate (rb, w );
W = x-> p-> right;
}
W-> color = x-> p-> color;
X-> p-> color = BLACK;
W-> right-> color = BLACK;
Left_rotate (rb, x-> p );
X = rb;
}
Else {// same as right and left exchanged
W = x-> p-> left;
If (w-> color = RED ){
W-> color = BLACK;
X-> p-> color = RED;
Right_rotate (rb, x-> p );
W = x-> p-> right;
}
If (w-> right-> color = BLACK) & (w-> left-> color = BLACK )){
W-> color = RED;
X = x-> p;
}
Else if (w-> left-> color = BLACK ){
W-> right-> color = BLACK;
W-> color = RED;
Left_rotate (rb, w );
W = x-> p-> left;
}
W-> color = x-> p-> color;
X-> p-> color = BLACK;
W-> left-> color = BLACK;
Right_rotate (rb, x-> p );
X = rb;
}
}
X-> color = BLACK;
}

Struct rb_tree * rb_delete (struct rb_tree * rb, struct rb_tree * z ){
Struct rb_tree * x, * y;
If (z-> left-> key = T_nil) | (z-> right-> key = T_nil ))
Y = z;
Else y = tree_successor (z );
If (y-> left-> key! = T_nil)
X = y-> left;
Else
X = y-> right;

X-> p = y-> p;

If (y-> p-> key = T_nil)
Rb = x;
Else if (y = x-> p-> left)
Y-> p-> left = x;
Else
Y-> p-> right = x;

If (y! = X) // copy y's data to z
Z-> key = y-> key;
If (y-> color = BLACK)
Rb_delete_fixup (rb, x );
Free (y );
Return rb;
}

Int main (){
Struct rb_tree * p, * root;
Struct rb_tree tree_nil = {BLACK, T_nil, & tree_nil };
Root = & tree_nil;
Root = rb_insert (root, 15 );
Root = rb_insert (root, 5 );
Root = rb_insert (root, 16 );
Root = rb_insert (root, 3 );
Root = rb_insert (root, 12 );
Root = rb_insert (root, 20 );
Root = rb_insert (root, 10 );
Root = rb_insert (root, 13 );
Root = rb_insert (root, 6 );
Root = rb_insert (root, 7 );
Root = rb_insert (root, 18 );
Root = rb_insert (root, 23 );
Rb_walk (root );
P = rb_search (root, 18 );
Root = rb_delete (root, p );
Rb_walk (root );
Return 1;
}

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.