The red and black trees in Nginx

Source: Internet
Author: User

Well, Nginx is a cover. The main introduction to the red and black trees some theoretical knowledge, nginx main source attached to the back. This article is not exhaustive, my level is not to that height.

Characteristics of red and black trees:

1. The red-black tree is a binary search tree.

2. Each node on the tree is either red or black.

3. If a node is red, then its left and right sub-nodes must be black.

4. The black node numbers passed from the root node to each leaf node path are the same.

5. The root node must be black.

It is important to understand these characteristics. It is because of these features that the red and black trees are guaranteed to be efficient. (As for why, I learned not fine, not to talk about.) )。

The insertion and deletion of red and black tree nodes is essentially a binary search tree rule. However, when the basic operation is completed, if you violate a red-black tree's characteristics, then you need to do some rotation operation to the red and black junction balance. So, a pretty part of the red and black tree Insert and delete action is the basic two-fork search tree Insert and delete. This article lists only those situations that require rotation processing.

Red-black Tree insert operation:

The contract is as follows: the parent node of the current operation node for X,x is the parent of P,p, Pp,p's sibling junction is S.

According to rule 4, the newly inserted node (X) must be red. If the parent node (P) of X is also red. In violation of rule 3, a rotation operation is required to satisfy the feature. It is divided into three cases.

I1:

X is red,p for red,s for black. It can be deduced that PP is also black.

    

Divided into three steps: The P black, the PP red, pp right rotation. (Reverse the same).

I2:

X is red,p for red,s for black. It can be deduced that PP is also black.

  

The p is rotated directly to the left, which becomes the I1. Follow the I1 steps to balance (reverse the same direction, in opposite directions).

I3:

X is red,p to red,s for red. It can be deduced that PP is black.

  

In this case, p and s are black, and the PP is placed red. This is a special case, if the parent of PP PPP is also red? Then the P node is recursive to the new x upward. Until PPP is black. If recursive to the root node, then set the root directly to black. (equivalent to the Black node count in each path + 1).

At this point, the red and black tree insert operation theory is all finished, I said clear?

 Red-Black Tree delete operation: 

  

Red and Black Tree Delete operation The first step also follows the law of binary search tree.

We assume that the node you want to delete is Y. It is divided into three situations:

    1. Y is the leaf node, then the Y node is deleted. The Y-node is replaced with null, which is recorded as X.
    2. Y is a single node, the y node is deleted, and Y's position is replaced with the effective child node of Y (left or right). Remember as X
    3. Y is a double node, find the smallest node x in the right subtree of the Y-node (this node left is definitely null). Swaps the values of x and Y (the color is the same). Then delete the X node (equivalent to deleting the y node).

At this point the deletion has been completed, the second step is to balance the red and black nodes, is the tree to meet the nature of red and black trees.

    1. If Y is red, removing the red node does not require a balanced operation.
    2. If Y is black,x is red. Set X to black and delete complete.
    3. If Y is black,x black. Some additional adjustments are required to meet the nature of the red-black tree.

The Convention is as follows: the current operation node for X,x's parent node is P,x's sibling knot for s (note here is the brother of X). The sub-node of S is the SL Sr.

D1:

X is black,s for red. The SL SR must be black.

  

The transformation does not make the tree satisfy the nature of the red-black tree, but instead transforms it into another case. (D2 D3 D4).

D2:

X is black for black,s. The SL SR is black.

Because X is deleted, the X branch has a black node less than the S branch. After the S is set red, the entire subtree branches black node balance (one less than the other branches). So set p to the new X. (It's easier to understand here than to draw).

D3:

X is black for black,s. Then SL is red SR bit black.

  

s place Red SL black. s right rotation. Converted into D4.

D4:

X is black for black,s. Then SL is black SR bit red.

Set S to the color of P, p to black. The SR is black. Left rotation p. So the left subtree is missing the black knot back. Delete complete.

It can be seen that when the delete node has left and right subtrees, only D4 will be able to actually complete the balance. D1 D2 D3 are converted to D4.

Speaking of the back of their own circle, feel like a fool. Write it all, or send it out.

Why is it that the theory above is so simple and rude? That's what Nginx says.

Insert Code:

voidNgx_rbtree_insert (ngx_rbtree_t*tree, ngx_rbtree_node_t *node) {ngx_rbtree_node_t**root, *temp, *Sentinel; /*a binary tree insert*/Root= (ngx_rbtree_node_t *) &tree->Root; Sentinel= tree->sentinel;//Sentinel is the Sentinel, and I think it's null.    if(*root = =Sentinel) {Node->parent =NULL; Node->left =Sentinel; Node->right =Sentinel;        Ngx_rbt_black (node); *root =node; return; } Tree->insert (*root, node, Sentinel);//Insert nodes by binary search tree    /*re-balance Tree*/     while(Node! = *root && ngx_rbt_is_red (node->parent)) {//balance the red and black knot.        if(Node->parent = = node->parent->parent->Left ) {Temp= node->parent->parent->Right ; if(ngx_rbt_is_red (temp)) {//I3Ngx_rbt_black (node->parent);                Ngx_rbt_black (temp); Ngx_rbt_red (Node->parent->parent); Node= node->parent->parent; } Else {                                            if(node = = node->parent->right) {//I2node = node->parent;                Ngx_rbtree_left_rotate (Root, Sentinel, node); } Ngx_rbt_black (Node->parent);//I1Ngx_rbt_red (node->parent->parent); Ngx_rbtree_right_rotate (Root, Sentinel, node->parent->parent); }        } Else{//reverse the same, in the opposite direction. temp = node->parent->parent->Left ; if(ngx_rbt_is_red (temp)) {Ngx_rbt_black (node-parent);                Ngx_rbt_black (temp); Ngx_rbt_red (Node->parent->parent); Node= node->parent->parent; } Else {                if(node = = node->parent->Left ) {Node= node->parent;                Ngx_rbtree_right_rotate (Root, Sentinel, node); } Ngx_rbt_black (Node-parent); Ngx_rbt_red (Node->parent->parent); Ngx_rbtree_left_rotate (Root, Sentinel, node->parent->parent); }}} ngx_rbt_black (*root);//no brain settings, any situation is right. }

Delete code:

voidNgx_rbtree_delete (ngx_rbtree_t*tree, ngx_rbtree_node_t *node)    {ngx_uint_t red; ngx_rbtree_node_t**root, *sentinel, *subst, *temp, *W; /*a binary tree delete*/Root= (ngx_rbtree_node_t *) &tree->Root; Sentinel= tree->sentinel;//Sentinel (NULL)    if(Node->left = = Sentinel) {//Case 1 2 Delete node Y is a single branch or leaf node .temp = node->Right ; Subst=node; } Else if(Node->right = = Sentinel) {//Case 1 2 Delete node Y is a single branch or leaf node .temp = node->Left ; Subst=node; } Else{//Case 1 Condition 3 delete node Y for double nodesubst = ngx_rbtree_min (node->Right , Sentinel); if(Subst->left! =Sentinel) {Temp= subst->Left ; } Else{Temp= subst->Right ; }    }    if(subst = = *root) {        *root =temp;        Ngx_rbt_black (temp); /*DEBUG Stuff*/node->left =NULL; Node->right =NULL; Node->parent =NULL; Node->key =0; return; } Red= ngx_rbt_is_red (subst);//record the color of y    if(subst = = subst->parent->left) {//here is the binary search tree according to the nature of the deletion of nodes after the regeneration of the two-fork search tree. Subst->parent->left =temp; } Else{subst->parent->right =temp; }    if(subst = =node) {Temp->parent = subst->parent; } Else {        if(Subst->parent = =node) {Temp->parent =subst; } Else{Temp->parent = subst->parent; } subst->left = node->Left ; Subst->right = node->Right ; Subst->parent = node->parent;        Ngx_rbt_copy_color (subst, node); if(Node = = *root) {            *root =subst; } Else {            if(node = = node->parent->Left ) {Node->parent->left =subst; } Else{node->parent->right =subst; }        }        if(Subst->left! =Sentinel) {subst->left->parent =subst; }        if(Subst->right! =Sentinel) {subst->right->parent =subst; }    }    /*DEBUG Stuff*/node->left =NULL; Node->right =NULL; Node->parent =NULL; Node->key =0; if(red) {//Delete node Y for Red Direct exit        return; }    /*a Delete fixup*/     while(Temp! = *root && ngx_rbt_is_black (temp)) {//Temp is the x in the above. Begin to balance the red and black knot points. Until x is red, or root is reached        if(temp = = temp->parent->Left ) {W= temp->parent->Right ; if(Ngx_rbt_is_red (W)) {//D1Ngx_rbt_black (W); Ngx_rbt_red (Temp-parent); Ngx_rbtree_left_rotate (Root, Sentinel, temp-parent); W= temp->parent->Right ; }            if(Ngx_rbt_is_black (W->left) && ngx_rbt_is_black (w->right)) {//D2ngx_rbt_red (W); Temp= temp->parent; } Else {                if(Ngx_rbt_is_black (W->right)) {//D3Ngx_rbt_black (w->Left );                    Ngx_rbt_red (w);                    Ngx_rbtree_right_rotate (Root, Sentinel, W); W= temp->parent->Right ; } ngx_rbt_copy_color (W, temp->parent);//D4Ngx_rbt_black (temp->parent); Ngx_rbt_black (W-Right ); Ngx_rbtree_left_rotate (Root, Sentinel, temp-parent); Temp= *Root; }        } Else{//reverse the same, in the opposite direction. W = temp->parent->Left ; if(ngx_rbt_is_red (w)) {ngx_rbt_black (w); Ngx_rbt_red (Temp-parent); Ngx_rbtree_right_rotate (Root, Sentinel, temp-parent); W= temp->parent->Left ; }            if(Ngx_rbt_is_black (W->left) && Ngx_rbt_is_black (w->Right ))                {ngx_rbt_red (w); Temp= temp->parent; } Else {                if(Ngx_rbt_is_black (w->Left )) {Ngx_rbt_black (w-Right );                    Ngx_rbt_red (w);                    Ngx_rbtree_left_rotate (Root, Sentinel, W); W= temp->parent->Left ; } ngx_rbt_copy_color (W, temp-parent); Ngx_rbt_black (Temp-parent); Ngx_rbt_black (W-Left ); Ngx_rbtree_right_rotate (Root, Sentinel, temp-parent); Temp= *Root;   }}} ngx_rbt_black (temp); //Place Black}

I wrote this really shit ah. Research Nginx source code to make a look at it. The red-and-black tree studied the volume of soil rewrite. Tap the groove.

  

The red and black trees in Nginx

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.