Nginx之紅/黑樹狀結構
/** Copyright (C) Igor Sysoev* Copyright (C) Nginx, Inc.*/#ifndef _NGX_RBTREE_H_INCLUDED_#define _NGX_RBTREE_H_INCLUDED_#include <ngx_config.h>#include <ngx_core.h>typedef ngx_uint_t ngx_rbtree_key_t;typedef ngx_int_t ngx_rbtree_key_int_t;typedef struct ngx_rbtree_node_s ngx_rbtree_node_t;// 紅/黑樹狀結構struct ngx_rbtree_node_s {// 無符號整形的關鍵字ngx_rbtree_key_t key;// 左子節點ngx_rbtree_node_t *left;// 右子節點ngx_rbtree_node_t *right;// 父節點ngx_rbtree_node_t *parent;// 節點的顏色,0表示黑色,1表示紅色u_char color;// 僅1個位元組的節點資料。由於表示的空間太小,所以一般很少使用。u_char data;};typedef struct ngx_rbtree_s ngx_rbtree_t;typedef void (*ngx_rbtree_insert_pt) (ngx_rbtree_node_t *root,ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);struct ngx_rbtree_s {// 指向樹的根節點。ngx_rbtree_node_t *root;// 指向NIL哨兵節點ngx_rbtree_node_t *sentinel;// 表示紅/黑樹狀結構添加元素的函數指標,它決定在添加新節點時的行為究竟是替換還是新增ngx_rbtree_insert_pt insert;};#define ngx_rbtree_init(tree, s, i) \ngx_rbtree_sentinel_init(s); \(tree)->root = s; \(tree)->sentinel = s; \(tree)->insert = ivoid ngx_rbtree_insert(ngx_thread_volatile ngx_rbtree_t *tree,ngx_rbtree_node_t *node);void ngx_rbtree_delete(ngx_thread_volatile ngx_rbtree_t *tree,ngx_rbtree_node_t *node);void ngx_rbtree_insert_value(ngx_rbtree_node_t *root, ngx_rbtree_node_t *node,ngx_rbtree_node_t *sentinel);void ngx_rbtree_insert_timer_value(ngx_rbtree_node_t *root,ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);#define ngx_rbt_red(node) ((node)->color = 1)#define ngx_rbt_black(node) ((node)->color = 0)#define ngx_rbt_is_red(node) ((node)->color)#define ngx_rbt_is_black(node) (!ngx_rbt_is_red(node))#define ngx_rbt_copy_color(n1, n2) (n1->color = n2->color)/* a sentinel must be black */#define ngx_rbtree_sentinel_init(node) ngx_rbt_black(node)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;}#endif /* _NGX_RBTREE_H_INCLUDED_ *//** Copyright (C) Igor Sysoev* Copyright (C) Nginx, Inc.*/#include <ngx_config.h>#include <ngx_core.h>/** The red-black tree code is based on the algorithm described in* the "Introduction to Algorithms" by Cormen, Leiserson and Rivest.*/static ngx_inline void ngx_rbtree_left_rotate(ngx_rbtree_node_t **root,ngx_rbtree_node_t *sentinel, ngx_rbtree_node_t *node);static ngx_inline void ngx_rbtree_right_rotate(ngx_rbtree_node_t **root,ngx_rbtree_node_t *sentinel, ngx_rbtree_node_t *node);void ngx_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 (*root == sentinel) { //空樹node->parent = NULL;node->left = sentinel;node->right = sentinel;ngx_rbt_black(node);*root = node;return;}tree->insert(*root, node, sentinel);/* re-balance tree */while (node != *root && ngx_rbt_is_red(node->parent)) {if (node->parent == node->parent->parent->left) {temp = node->parent->parent->right;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->right) {node = node->parent;ngx_rbtree_left_rotate(root, sentinel, node);}ngx_rbt_black(node->parent);ngx_rbt_red(node->parent->parent);ngx_rbtree_right_rotate(root, sentinel, node->parent->parent);}} else {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);}void ngx_rbtree_insert_value(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node,ngx_rbtree_node_t *sentinel) {ngx_rbtree_node_t **p;for (;;) {p = (node->key < temp->key) ? &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);}void ngx_rbtree_insert_timer_value(ngx_rbtree_node_t *temp,ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel) {ngx_rbtree_node_t **p;for (;;) {/** Timer values* 1) are spread in small range, usually several minutes,* 2) and overflow each 49 days, if milliseconds are stored in 32 bits.* The comparison takes into account that overflow.*//* node->key < temp->key */p = ((ngx_rbtree_key_int_t) node->key - (ngx_rbtree_key_int_t) 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);}void ngx_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;//找到y和x節點if (node->left == sentinel) {temp = node->right;subst = node;} else if (node->right == sentinel) {temp = node->left;subst = node;} else {subst = ngx_rbtree_min(node->right, sentinel);if (subst->left != sentinel) {temp = subst->left;} else {temp = subst->right;}}//y節點為root節點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);//記錄y節點顏色//y父的孩子節點if (subst == subst->parent->left) {subst->parent->left = temp;} else {subst->parent->right = temp;}//y孩子的父節點if (subst == node) {//只有一個孩子節點temp->parent = subst->parent;} else {if (subst->parent == node) {temp->parent = subst;} else {temp->parent = subst->parent;}//y節點copy z節點屬性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;}}//y節點的父節點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;}/* a delete fixup */while (temp != *root && ngx_rbt_is_black(temp)) {if (temp == temp->parent->left) {w = temp->parent->right;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;}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->right)) {ngx_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);ngx_rbt_black(temp->parent);ngx_rbt_black(w->right);ngx_rbtree_left_rotate(root, sentinel, temp->parent);temp = *root;}} else {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);}static ngx_inline void ngx_rbtree_left_rotate(ngx_rbtree_node_t **root,ngx_rbtree_node_t *sentinel, ngx_rbtree_node_t *node) {ngx_rbtree_node_t *temp;//1、設定節點ytemp = node->right;//2、將y的左子樹作為x的右子樹node->right = temp->left;if (temp->left != sentinel) {temp->left->parent = node;}//3、連結y與x的父節點temp->parent = node->parent;if (node == *root) {*root = temp;} else if (node == node->parent->left) {node->parent->left = temp;} else {node->parent->right = temp;}//4、x作為y的左子樹temp->left = node;node->parent = temp;}static ngx_inline void ngx_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;}
以上就是Nginx之紅/黑樹狀結構的內容,更多相關內容請關注topic.alibabacloud.com(www.php.cn)!