Nginx Red and black tree structure ngx_rbtree_t

Source: Internet
Author: User

Overview

About the basic knowledge of red and black trees in the previous article has been introduced, want to learn more about red and black tree can refer to the article "Data structure-red black tree", here is only simple to nginx in the red and black tree source of the analysis, Nginx red and black tree source code is realized with the introduction of the algorithm is the same.

Red and black tree structure

typedef ngx_ uint_t ngx_rbtree_key_t;typedef ngx_int_t ngx_rbtree_key_int_t;/* red-black tree node structure */typedef struct ngx_rbtree_node_s ngx_rbtre     E_node_t;struct ngx_rbtree_node_s {ngx_rbtree_key_t key;    /* Key value of node */ngx_rbtree_node_t *left;   /* Left child of Node */ngx_rbtree_node_t *right;  /* Node Right child */ngx_rbtree_node_t *parent;   /* The father of the node */U_char color;    /* The color of the node */U_char data; /* */};typedef struct ngx_rbtree_s ngx_rbtree_t;typedef void (*ngx_rbtree_insert_pt) (ngx_rbtree_node_t *root, NGX_RBT    ree_node_t *node, ngx_rbtree_node_t *sentinel);/* Red-black tree structure */struct ngx_rbtree_s {ngx_rbtree_node_t *root;  /* point to the root node of the tree */ngx_rbtree_node_t *sentinel;/* to the leaf node of the tree nil */ngx_rbtree_insert_pt insert; /* Add the function pointer of the element node to solve the conflict problem with the same key value but different color nodes; * The function pointer determines whether the new node's behavior is new or replaces the original node */}; 

Operation of red and black trees

Initialize operation

/* to color the nodes, 1 means red, 0 is black */#define NGX_RBT_RED (node)->color = 1) #define Ngx_rbt_black ((nod          e)->color = 0)/* Determine the color of the node */#define NGX_RBT_IS_RED (node)->color) #define NGX_RBT_IS_BLACK (node) !ngx_rbt_is_red (node)/* Copy the color of a node */#define NGX_RBT_COPY_COLOR (N1, n2) (N1->color = n2->color)/* Node with black  Macro definition *//* A sentinel must be black */#define NGX_RBTREE_SENTINEL_INIT (node) ngx_rbt_black (node)/* Initializes the red-black tree, which is the empty red-black tree *//* Trees                                               is a pointer to a red-black tree, * s is a nil node of a red-black tree, * I represents a function pointer, determines whether the node is new or replaced */#define NGX_RBTREE_INIT (tree, S, i)                                                  Ngx_rbtree_sentinel_init (s);                                                             (tree)->root = s;                                                         (tree)->sentinel = s; (tree)->insert = i 

Rotation operation

/* Left rotation operation */static Ngx_inline voidngx_rbtree_left_rotate (ngx_rbtree_node_t **root, ngx_rbtree_node_t *sentinel, NGX_RBT    ree_node_t *node) {ngx_rbtree_node_t *temp; temp = node->right;/* Temp is the right child for node nodes */node->right = temp->left;/* Sets the right child for node nodes to the left child of temp */if (temp->    Left! = Sentinel) {temp->left->parent = node;    } temp->parent = node->parent;    if (node = = *root) {*root = temp;    } else if (node = = node->parent->left) {node->parent->left = temp;    } else {node->parent->right = temp;    } temp->left = node; Node->parent = temp;} Static Ngx_inline voidngx_rbtree_right_rotate (ngx_rbtree_node_t **root, ngx_rbtree_node_t *sentinel, Ngx_rbtree_node    _t *node) {ngx_rbtree_node_t *temp;    temp = node->left;    Node->left = temp->right;    if (temp->right! = Sentinel) {temp->right->parent = node;    } temp->parent = node->parent; if (node = = *roOT) {*root = temp;    } else if (node = = node->parent->right) {node->parent->right = temp;    } else {node->parent->left = temp;    } temp->right = node; Node->parent = temp;}

Insert operation

/* Get the node with the lowest red and black tree key value */static ngx_inline ngx_rbtree_node_t *ngx_rbtree_min (ngx_rbtree_node_t *node, ngx_rbtree_node_t *    Sentinel) {while (Node->left! = Sentinel) {node = node->left; } return node; /* Insert node *//* insert node Step: * 1, first insert the new node according to the binary search tree insert operation, * 2, and then color the new node red (avoid damaging the red and black Tree Properties 5); * 3, in order to maintain the nature of red and black trees, adjust the red and black tree nodes (coloring and rotation) to meet the nature of Voidngx_rbtree_insert (Ngx_thread_volatile 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;        /* If the red and black tree is empty, it is relatively simple, the new node as the root node, * and initialize the node to meet the nature of the red black tree * * if (*root = = Sentinel) {node->parent = NULL;        Node->left = Sentinel;        Node->right = Sentinel;        Ngx_rbt_black (node);        *root = node;    Return    }/* If the red and black tree is not empty, follow the insert operation of the binary search tree * This operation is provided by the function pointer */Tree->insert (*root, node, Sentinel); /* re-balance Tree */* Adjust the red and black trees to satisfy the nature, * actually this is just destroyingThe Property 4: If a node is red, then the child node is black; * If you break the property 4, the new node and its Father node node->parent are red; */while (node! = *root && ng X_rbt_is_red (node->parent)) {/* If node's father is the left child of its grandfather node */if (node->parent = = Node->parent->paren T->left) {temp = node->parent->parent->right;/* temp node is node's uncle nodes */* Case1:node's uncle node is Red */* At this point, node's father and Uncle nodes are red; * Workaround: Color node's father and uncle nodes to be black, coloring node grandfather nodes red;                Will break the nature of the red-black tree; */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 {/* Case2:node's uncle node is black and node is the Father node of the right child */* At this time, with node father nodes left rotation, so that case2 into case3;             */if (node = = node->parent->right) {node = node->parent;       Ngx_rbtree_left_rotate (Root, Sentinel, node); }/* Case3:node's uncle node is black and node is the Father node of the left child */* First, the node's father nodes are colored black, the grandfather nodes are colored red;                Then a right rotation is performed with the grandfather node; */Ngx_rbt_black (node->parent);                Ngx_rbt_red (node->parent->parent);            Ngx_rbtree_right_rotate (Root, Sentinel, node->parent->parent); }} else {/* If node's father is the right child of its grandfather node */* Here is symmetric with the above case, no more explanation */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); }}}/* The root node must be black */ngx_rbt_black (*root);} /* Here just insert the node into the red-black tree, and there is no judging whether it satisfies the nature of the red-black tree; * Similar to the binary search tree insert operation, this function for red black tree insert operation function pointer; */voidngx_rbtree_insert_value (ngx_rbtree_    node_t *temp, ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel) {ngx_rbtree_node_t **p; for (;;) {/* Determine the size of the node key value and the TEMP node key value to determine whether node is inserted into the Zuozi or right subtree of the TEMP node */p = (Node->key < Temp->key)? &AMP;TEMP-&G        T;left: &temp->right;        if (*p = = Sentinel) {break;    } temp = *p;    }/* Initialize node node and color Red */*p = node;    Node->parent = temp;    Node->left = Sentinel;    Node->right = Sentinel; ngx_rbt_red (node);} Voidngx_rbtree_insert_timer_value (ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel) {ng  x_rbtree_node_t**p; for (;;) {/* * Timer values * 1) is spread in small range, usually several minutes, * 2) and Overf         Low, if milliseconds is stored in.         * The comparison takes into account that overflow.            */* Node->key < Temp->key */P = ((ngx_rbtree_key_int_t) (Node->key-temp->key) < 0) ?        &temp->left: &temp->right;        if (*p = = Sentinel) {break;    } temp = *p;    } *p = node;    Node->parent = temp;    Node->left = Sentinel;    Node->right = Sentinel; ngx_rbt_red (node);}

Delete operation

/* Delete node */voidngx_rbtree_delete (ngx_thread_volatile 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;    /* The following is the get Temp node value, temp saved node is ready to replace nodes node; * Subst is the successor node of the node to be replaced; */* CASE1: If the node does not have a left child (there is a situation where the right child exists or does not exist) */        if (Node->left = = Sentinel) {temp = node->right;    subst = node;        } else if (node->right = = Sentinel) {/* Case2:node node exists left child, but no right child */temp = node->left;    subst = node; The else {/* Case3:node node has both the left child and the right child */subst = Ngx_rbtree_min (node->right, Sentinel);/* Gets the node node's subsequent nodes */I        F (subst->left! = Sentinel) {temp = subst->left;        } else {temp = subst->right;        }/* If the replaced node subst is the root node, the temp replacement subst is called the root node */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 records the color of the SUBST node */red = ngx_rbt_is_red (subst);    /* The TEMP node replaces the SUBST node */if (subst = = subst->parent->left) {subst->parent->left = temp;    } else {subst->parent->right = temp;    }/* Based on whether subst is processing for node nodes */if (subst = = node) {temp->parent = subst->parent;        } else {if (subst->parent = = node) {temp->parent = subst;        } else {temp->parent = subst->parent;        }/* Copy node properties */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) {return; }/* Starts with the nature of the red-black tree */* a DELETE fixup */* is processed according to the TEMP node if temp is not the root node and is black */while (temp! = *root && Ngx_rbt_is_black (temp)) {/* If TEMP is the left child of its Father node */if (temp = = Temp->parent->left) {w = temp- >parent->right;/* W is the sibling node for temp */* Case a:temp Brother node is red */* Workaround: * 1, change w node and temp parent The color of the parent node; * 2, to the temp Father's Day to do a left rotation, at this time, the sibling node of temp is a child node of W before rotation, the child node color is black; * 3, at this time, case a has been converted to case B, case C or Case D; */if (ngx_rbt_is_Red (W)) {ngx_rbt_black (w);                Ngx_rbt_red (temp->parent);                Ngx_rbtree_left_rotate (Root, Sentinel, temp->parent);            W = temp->parent->right; }/* Case B:temp's brother node W is black, and the two subnodes of W are black */* Workaround: * 1, change the color of the W node; * 2, the parent of temp                The parent node as the new temp node; */if (Ngx_rbt_is_black (w->left) && ngx_rbt_is_black (w->right)) {                Ngx_rbt_red (w);            temp = temp->parent;                 The sibling node of the else {/* case c:temp is black, and W's left child is red, and the right child is black */* Solution: * 1, will change the color of W and its left child; * 2, a right rotation of the W node; * 3, at this time, the new sibling node of temp W has a red right child's black node, to case D; */if (ngx_r                    Bt_is_black (W->right)) {ngx_rbt_black (w->left);                    Ngx_rbt_red (w);                    Ngx_rbtree_right_rotate (Root, Sentinel, W); W = Temp->parent->rigHt }/* Case d:temp Brother node W is black, and W's right child is red */* Workaround: * 1, set the W node to the color of the temp Father node, temp parent                 The parent node is set to black; * 2, W's right child is set to black; * 3, the Father node of temp is left rotated once; * 4. Root node is set to the TEMP node;                Ngx_rbt_copy_color (w, temp->parent);                Ngx_rbt_black (temp->parent);                Ngx_rbt_black (W->right);                Ngx_rbtree_left_rotate (Root, Sentinel, temp->parent);            temp = *root;            }} else {/* Here is the case for the left child of the temp node for its Father node */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);}


Nginx Red and black tree structure ngx_rbtree_t

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.