Application scenario of red black tree
- Process scheduling cfs
- epoll
- nginx timer
- std::map
Properties of red black tree
- The node is red or black
- The root node is black
- The leaf node (NIL) is black
- The child nodes of red nodes can only be black
- The number of black nodes (black height) of the path from the root node to any leaf node is equal
Red black tree definition
typedef int KEY_TYPE; typedef struct _rbtree_node { unsigned char color; struct _rbtree_node *left; struct _rbtree_node *right; struct _rbtree_node *parent; KEY_TYPE key; void *value; } rbtree_node; typedef struct _rbtree { rbtree_node *root; rbtree_node *nil; //All Nils point to this node };
Left and right rotation
To change three links, six pointers (top, x-y, b)
void _left_rotate(rbtree *T, rbtree_node *x) { rbtree_node *y = x->right; x->right = y->left; if(y->left) { y->left->parent = x; } y->parent = x->parent; if(x->parent == T->nil) { T->root = x; } else if (x->parent->left == x) { x->parent->left = y; } else { x->parent->right = y; } y->left = x; x->parent = y; }
Red black tree insertion
- Find the location to insert and its parent node
- The newly inserted node is marked in red
- Resolve possible conflicts (4)
Three cases
The parent node is red and the grandfather node must be black
- The uncle node is red
->Both the parent node and the uncle node are set to black, the grandfather is set to red, and the current node becomes the grandfather (push the red up) - The tertiary node is black, and the current node is the right child of the parent node
->The parent node rotates to the left and adjusts the color, which is converted to case 3 - The tertiary node is black, and the current node is the left child of the parent node
->Rotate the node right and adjust the color
Finally, set the root node to black
RB-INSERT-FIXUP(T, z) 01 while color[p[z]] = RED // If "parent node of current node (z) is red", perform the following processing. 02 do if p[z] = left[p[p[z]]] // If "parent node of z" is "left child of grandfather node of z", perform the following processing. 03 then y ← right[p[p[z]]] // Set y to "z's uncle node (the right child of z's grandfather node)" 04 if color[y] = RED // Case 1 condition: uncle is red 05 then color[p[z]] ← BLACK ▹ Case 1 // (01) set "parent node" to black. 06 color[y] ← BLACK ▹ Case 1 // (02) set uncle node to black. 07 color[p[p[z]]] ← RED ▹ Case 1 // (03) set "grandfather node" to "red". 08 z ← p[p[z]] ▹ Case 1 // (04) set "grandfather node" to "current node" (red node) 09 else if z = right[p[z]] // Case 2 condition: the uncle is black and the current node is the right child 10 then z ← p[z] ▹ Case 2 // (01) set "parent node" as "new current node". 11 LEFT-ROTATE(T, z) ▹ Case 2 // (02) rotate left with "new current node" as the fulcrum. 12 color[p[z]] ← BLACK ▹ Case 3 // Case 3 condition: the uncle is black and the current node is the left child. (01) set "parent node" to "black". 13 color[p[p[z]]] ← RED ▹ Case 3 // (02) set "grandfather node" to "red". 14 RIGHT-ROTATE(T, p[p[z]]) ▹ Case 3 // (03) carry out right rotation with the "grandfather node" as the fulcrum. 15 else (same as then clause with "right" and "left" exchanged) // If the "parent node of z" is the "right child of the grandfather node of z", swap the "right" and "left" positions in the above operations, and then execute them in turn. 16 color[root[T]] ← BLACK
Red black tree delete node
- Find the node. If the number of child nodes = 0, delete it directly. If the number of child nodes = 1, replace it with a child node. If = 2, find the subsequent node, copy the contents of the subsequent node to the current node, and then delete the subsequent node
- If the deleted node is black, the current node has one more layer of black
- If the current node is black + red, set the current node to black and end
- Otherwise, rebalance
Delete rebalance
- The sibling node is red - > the parent node is left-handed, which is converted to 2 / 3 / 4
- The brother node is black, and the two child nodes of the brother are black - > set the brother node as red, the current node as black, and the current node as the parent node) (push the black up)
- Brother is black, brother's left child is red - > converted to 4 through right-handed brother
- The brother is black. The right child of the brother is red - > the parent node rotates left. Borrow a red node and set it to black on the left. In this way, there will be no double black. End
RB-DELETE-FIXUP(T, x) 01 while x ≠ root[T] and color[x] = BLACK 02 do if x = left[p[x]] 03 then w ← right[p[x]] // If "x" is "the left child of its parent node", set "w" to "the uncle of x" (that is, x is the right child of its parent node) 04 if color[w] = RED // Case 1: x is the "black + black" node, and the brother node of x is red. (at this time, the parent node of x and the child node of the brother node of x are black nodes). 05 then color[w] ← BLACK ▹ Case 1 // (01) set the sibling node of x to "black". 06 color[p[x]] ← RED ▹ Case 1 // (02) set the parent node of x to "red". 07 LEFT-ROTATE(T, p[x]) ▹ Case 1 // (03) rotate the parent node of x to the left. 08 w ← right[p[x]] ▹ Case 1 // (04) after left rotation, reset the brother node of x. 09 if color[left[w]] = BLACK and color[right[w]] = BLACK // Case 2: x is the "black + black" node, the brother node of x is black, and the two children of the brother node of x are black. 10 then color[w] ← RED ▹ Case 2 // (01) set the sibling node of x to "red". 11 x ← p[x] ▹ Case 2 // (02) set "parent node of X" to "new x node". 12 else if color[right[w]] = BLACK // Case 3: x is the "black + black" node, and the brother node of x is black; The left child of the brother node of x is red and the right child is black. 13 then color[left[w]] ← BLACK ▹ Case 3 // (01) set the left child of the x brother node to "black". 14 color[w] ← RED ▹ Case 3 // (02) set the x sibling node to "red". 15 RIGHT-ROTATE(T, w) ▹ Case 3 // (03) right rotate the sibling node of x. 16 w ← right[p[x]] ▹ Case 3 // (04) after right rotation, reset the brother node of x. 17 color[w] ← color[p[x]] ▹ Case 4 // Case 4: x is the "black + black" node, and the brother node of x is black; The right child of the sibling node of x is red. (01) assign the color of the parent node of x to the brother node of x. 18 color[p[x]] ← BLACK ▹ Case 4 // (02) set the x parent node to "black". 19 color[right[w]] ← BLACK ▹ Case 4 // (03) set the right sub section of the x sibling node to "black". 20 LEFT-ROTATE(T, p[x]) ▹ Case 4 // (04) left rotate the parent node of x. 21 x ← root[T] ▹ Case 4 // (05) set "x" to "root node". 22 else (same as then clause with "right" and "left" exchanged) // If "x" is "the right child of its parent node", swap "right" and "left" in the above operations, and then execute them in turn. 23 color[x] ← BLACK
reference material
[1] Zero sound education Linux C/C + + back-end server architecture development 1.1.1
[2] The principle and algorithm of red black tree (I) are introduced in detail https://www.cnblogs.com/skywang12345/p/3245399.html