c/c++Linux background development course notes - 1.1.1 red black tree

Application scenario of red black tree

  • Process scheduling cfs
  • epoll
  • nginx timer
  • std::map

Properties of red black tree

  1. The node is red or black
  2. The root node is black
  3. The leaf node (NIL) is black
  4. The child nodes of red nodes can only be black
  5. 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

  1. Find the location to insert and its parent node
  2. The newly inserted node is marked in red
  3. Resolve possible conflicts (4)

Three cases

The parent node is red and the grandfather node must be black

  1. 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)
  2. 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
  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

  1. 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
  2. If the deleted node is black, the current node has one more layer of black
  3. If the current node is black + red, set the current node to black and end
  4. Otherwise, rebalance

Delete rebalance

  1. The sibling node is red - > the parent node is left-handed, which is converted to 2 / 3 / 4
  2. 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)
  3. Brother is black, brother's left child is red - > converted to 4 through right-handed brother
  4. 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

Tags: C data structure

Posted on Mon, 22 Nov 2021 12:29:20 -0500 by synking