Preface:
1. Some readers have responded that I have read my previous articles and I still have a thorough understanding of the red and black trees.
2. I personally think that, if I use diagrams + code to describe various insertion and deletion situations step by step, they may be more intuitive and easy to understand.
3. Since I have written a red/black tree, I must write it well to make readers fully understand it.
Compared with the three articles related to the red and black trees, this article mainly provides the following improvements:
1. Maps graphs, text descriptions, and code writing, which are clear and clear.
2. Macro Summary: understanding of the nature and insertion and deletion of the red and black trees.
3. The code is more direct. It combines graphs to give you the most intuitive feeling and thoroughly understand the red and black trees.
OK. First of all, you should be clear about the following points:
I. Five PROPERTIES OF THE RED/black tree:
1) each node is either red or black.
2) The root node is black.
3) each leaf node, that is, the null node (NiL) is black.
4) if a node is red, the two sons are black.
5) for each node, all paths from the node to its child node contain the same number of black nodes.
Ii. Situations of red/Black Tree insertion:
Case 1: Uncle y of Z is red.
Case 2: Uncle y of Z is black and Z is the right child
Case 3: Uncle y of Z is black and Z is left child
Iii. Deletion of red/black trees.
Case 1: X's brother w is red.
Case 2: Brother W of X is black, and both children of W are black.
Case 3: X's brother w is black, W's left child is red, and W's right child is black.
Case 4: X's brother w is black and W's right child is red.
In addition, it must be clear that:
Iv. We know that after a red/black tree inserts or deletes a node,
It may violate or damage the original property of the red/black tree,
Therefore, in order to make the tree after the node is inserted or deleted remain a new red/black tree,
We need to do the following:
1. Partial node color, re-coloring
2. Adjust the direction of some pointers, that is, left and right.
V:
1) red and black tree insert, delete node operation, RB-INSERT (T, Z), RB-DELETE (T, Z)
2) After the red/black tree has been inserted or deleted,
In order to maintain the original red and black properties of the red and black trees, the restoration and maintenance of the red and black properties are performed.
Such as RB-INSERT-FIXUP (T, Z), RB-DELETE-FIXUP (t, x)
I have already elaborated on the above five points in my previous two articles many times. I hope that you have understood them thoroughly.
---------------------------------------------------------------------
This article focuses on Graphic analysis of various situations in which the Red/black tree inserts and deletes nodes to maintain the red/black nature.
[The insertion and deletion situations below correspond to the implementation and analysis of the Red-black tree algorithm in my second article.]
OK.
1. In the following analysis, we agree:
The node to be inserted is, n
Father's Day, P
Grandfather node, G
Uncle node, u
Sibling node, S
As shown in, find the grandfather and Uncle nodes of a node:
Node grandparent (node N) // grandfather
{
Return N-> parent;
}
Node uncle (node N) // uncle
{
If (n-> parent = grandparent (N)-> left)
Return grandparent (N)-> right;
Else
Return grandparent (N)-> left;
}
Ii. Situations of red/Black Tree Insertion
Scenario 1: The new node N is located on the root of the tree and has no parent node.
Void insert_case1 (node N ){
If (n-> parent = NULL)
N-> color = black;
Else
Insert_case2 (N );
}
Case 2: the parent node P of the new node is black.
Void insert_case2 (node N ){
If (n-> parent-> color = black)
Return;/* the tree is still valid */
Else
Insert_case3 (N );
}
Case 3: the parent node P and Uncle node u are all red,
[In the second article, 1: Z's uncle is red.]
Void insert_case3 (node N ){
If (Uncle (n )! = NULL & Uncle (N)-> color = red ){
N-> parent-> color = black;
Uncle (N)-> color = black;
Grandparent (N)-> color = Red;
Insert_case1 (grandparent (n); // because the grandfather node may be red, it violates Nature 4, recursion 1.
}
Else
Insert_case4 (n); // otherwise, Uncle should be black and go to the following scenario 4 for handling.
At this time, the newly inserted node n is the Left or Right subnode of P.Case 3Only show N as the left sub of P.
Case 4: the parent node P is red, and the uncle node u is black or nil;
Insert NodeN is the right child of parent node p.The parent node P is the left child of the parent node.
[For my second article, the Case 2: Z's uncle is black and Z is the right child]
Void insert_case4 (node N ){
If (n = N-> parent-> Right & N-> parent = grandparent (N)-> left ){
Rotate_left (n-> parent );
N = N-> left;
} Else if (n = N-> parent-> left & N-> parent = grandparent (N)-> right ){
Rotate_right (n-> parent );
N = N-> right;
}
Insert_case5 (n); // go to the following scenario 5 for processing.
Case 5: the parent node P is red, while the uncle node u is black or nil,
Node TO BE INSERTEDN is the left child of its parent node.The parent node P is the left child of its parent G.
[For my second article, Case 3: Z's uncle is black and Z is a left child.]
Void insert_case5 (node N ){
N-> parent-> color = black;
Grandparent (N)-> color = Red;
If (n = N-> parent-> left & N-> parent = grandparent (N)-> left ){
Rotate_right (grandparent (n ));
} Else {
/* Reversed. n is the right child of its parent node, and P is the right child of its parent G */
Rotate_left (grandparent (n ));
}
}
Iii. Deletion of red/black trees
As agreed above, if the sibling node is set to S, we use the following function to find the sibling node:
Struct node * sibling (struct node * n) // find the sibling Node
{
If (n = N-> parent-> left)
Return N-> parent-> right;
Else
Return N-> parent-> left;
}
Case 1: n is the new root.
Void
Delete_case1 (struct node * n)
{
If (n-> parent! = NULL)
Delete_case2 (N );
}
Case 2: Brother node S is red
[In my second article, the Case 1: X's brother w is red.]
Void delete_case2 (struct node * n)
{
Struct node * s = sibling (N );
If (S-> color = red ){
N-> parent-> color = Red;
S-> color = black;
If (n = N-> parent-> left)
Rotate_left (n-> parent); // left-hand
Else
Rotate_right (n-> parent );
}
Delete_case3 (N );
}
Case 3: Brother node S is black, and both sons of S are black. But n's parent node P is black.
[In my second article, the Case 2: The brother w of X is black, and both sons of brother w are black.
(Here, the parent node P is black)]
Void delete_case3 (struct node * n)
{
Struct node * s = sibling (N );
If (n-> parent-> color = black )&&
(S-> color = black )&&
(S-> left-> color = black )&&
(S-> right-> color = black )){
S-> color = Red;
Delete_case1 (n-> parent );
} Else
Delete_case4 (N );
}
Case 4:Sibling NodeS is black, and S's son is black, but n's father P is red.
[In my second article, the Case 2: The brother w of X is black, and the two children of W are black.
(Here, the parent node P is red)]
Void delete_case4 (struct node * n)
{
Struct node * s = sibling (N );
If (n-> parent-> color = red )&&
(S-> color = black )&&
(S-> left-> color = black )&&
(S-> right-> color = black )){
S-> color = Red;
N-> parent-> color = black;
} Else
Delete_case5 (N );
}
Case 5: Brother S is black, his left son is red, his right son is black, and N is his father's left son.
// In this case, it is finally converted to the following situation 6.
[Corresponding to my second article, Case 3: X's brother w is black, W's left child is red, and W's right child is black.]
Void delete_case5 (struct node * n)
{
Struct node * s = sibling (N );
If (S-> color = black)
If (n = N-> parent-> left )&&
(S-> right-> color = black )&&
(S-> left-> color = red )){
// This last test is trivial too due to cases 2-4.
S-> color = Red;
S-> left-> color = black;
Rotate_right (s );
} Else if (n = N-> parent-> right )&&
(S-> left-> color = black )&&
(S-> right-> color = red )){
// This last test is trivial too due to cases 2-4.
S-> color = Red;
S-> right-> color = black;
Rotate_left (s );
}
}
Delete_case6 (n); // go to scenario 6.
Case 6: The Brother node S is black, the right son of S is red, and N is his father's left son.
[In my second article, the case 4: X's brother w is black and W's right child is red.]
Void delete_case6 (struct node * n)
{
Struct node * s = sibling (N );
S-> color = N-> parent-> color;
N-> parent-> color = black;
If (n = N-> parent-> left ){
S-> right-> color = black;
Rotate_left (n-> parent );
} Else {
S-> left-> color = black;
Rotate_right (n-> parent );
}
}
// You can draw the 12 images from noon to evening. Hopefully, this article will help you understand.
Iv. Analysis of the time complexity of insertion and deletion of red/black trees
Because every red/black tree is also a special binary search tree,
Therefore, the read-only operation on the red/black tree is the same as that on the common Binary Search Tree.
However, the insert and delete operations on the red/black tree will no longer conform to the nature of the red/black tree.
Restoring the properties of the red/black tree requires a small amount of (O (log n) color changes (actually very fast) and
No more than three tree rotations (two insert operations ).
Although insertion and deletion are complex, the operation time can still be O (log n) times.
OK.
Postscript:
This red/black tree series has written four articles before and after. If the readers have read these four articles,
I have a thorough understanding of the red and black trees,
I will spend so much space and hours painting the red and black trees.
To truly understand a Data Structure and algorithm, the most important thing is to understand what is actually available and practical.
Thank you for sharing your experience in using the red-black tree structure and Algorithms in your current or future studies and work.
Thank you. : D.
----------------------------------------
Reprinted from: http://blog.csdn.net/v_JULY_v/article/details/6124989