/*

 * 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 {

    // 无符号整形的keyword

    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 = i









void 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、设置节点y

temp = 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之红黑树的更多相关文章

  1. 定时器管理:nginx的红黑树和libevent的堆

    libevent 发生超时后, while循环一次从堆顶del timer——直到最新调整的最小堆顶不是超时事件为止,(实际是del event),但是会稍后把这个timeout的 event放到ac ...

  2. 红黑树、B(+)树、跳表、AVL等数据结构,应用场景及分析,以及一些英文缩写

    在网上学习了一些材料. 这一篇:https://www.zhihu.com/question/30527705 AVL树:最早的平衡二叉树之一.应用相对其他数据结构比较少.windows对进程地址空间 ...

  3. 简单聊聊红黑树(Red Black Tree)

    ​ 前言 众所周知,红黑树是非常经典,也很非常重要的数据结构,自从1972年被发明以来,因为其稳定高效的特性,40多年的时间里,红黑树一直应用在许多系统组件和基础类库中,默默无闻的为我们提供服务,身边 ...

  4. 红黑树和AVL树的区别(转)

    add by zhj: AVL树和红黑树都是平衡二叉树,虽然AVL树是最早发明的平衡二叉树,但直接把平衡二叉树等价于AVL树,我认为非常不合适. 但很多地方都在这么用.两者的比较如下 平衡二叉树类型 ...

  5. 新秀nginx源代码分析数据结构篇(四)红黑树ngx_rbtree_t

    新秀nginx源代码分析数据结构篇(四)红黑树ngx_rbtree_t Author:Echo Chen(陈斌) Email:chenb19870707@gmail.com Blog:Blog.csd ...

  6. nginx 红黑树详解

    1 介绍 这部分终于整理完了,太耗时间了,留下来备忘吧! 之前看STL源码时,只是研究了红黑树的插入部分.在stl源码剖析的书中,也没有涉及到删除操作的分析,这次对删除操作也进行了详细的研究, 并且还 ...

  7. 在nginx启动后,如果我们要操作nginx,要怎么做呢 别增加无谓的上下文切换 异步非阻塞的方式来处理请求 worker的个数为cpu的核数 红黑树

    nginx平台初探(100%) — Nginx开发从入门到精通 http://ten 众所周知,nginx性能高,而nginx的高性能与其架构是分不开的.那么nginx究竟是怎么样的呢?这一节我们先来 ...

  8. 菜鸟nginx源码剖析数据结构篇(四)红黑树ngx_rbtree_t[转]

    菜鸟nginx源码剖析数据结构篇(四)红黑树ngx_rbtree_t Author:Echo Chen(陈斌) Email:chenb19870707@gmail.com Blog:Blog.csdn ...

  9. Nginx数据结构之红黑树ngx_rbtree_t

    1. 什么是红黑树? 1.1 概述 红黑树实际上是一种自平衡二叉查找树. 二叉树是什么?二叉树是每个节点最多有两个子树的树结构,每个节点都可以用于存储数据,可以由任 1 个节点访问它的左右 子树或父节 ...

随机推荐

  1. mysql-MHA 故障收集

    在manager 主机上开启监控服务,启动不了 [root@manager ~]# managerStart [] [root@manager ~]# managerStatus app1 is st ...

  2. 在vc6里头文件sys/timeb.h里struct timeb各变量的具体含义?

    timeb的定义:struct _timeb{         time_t time;          unsigned short millitm;          short timezon ...

  3. 使用EventHandler传递参数

    1.MouseEventHandler和EventHandler传递参数的局限性分析 开发过程中,特别是使用自定义控件时,常常需要对一个控件的click,mouseDown,mouseUp等事件的处理 ...

  4. Guava源码学习(三)ImmutableCollection

    基于版本:Guava 22.0 Wiki:Immutable collections 0. ImmutableCollection简介 类似于JDK的Collections.unmodifiableX ...

  5. Codeforces Round #306 (Div. 2) A. Two Substrings【字符串/判断所给的字符串中是否包含不重叠的“BA” “AB”两个字符串】

    A. Two Substrings time limit per test 2 seconds memory limit per test 256 megabytes input standard i ...

  6. Properties文件工具读取类

    import java.io.IOException;import java.io.InputStream;import java.util.Properties; public class Comm ...

  7. Selenium IDE自动化录制脚本

  8. 磁盘镜像工具Guymager

    磁盘镜像工具Guymager   在数字取证中,经常需要对磁盘制作镜像,以便于后期分析.Kali Linux提供一款轻量级的磁盘镜像工具Guymager.该工具采用图形界面化方式,提供磁盘镜像和磁盘克 ...

  9. Strobogrammatic Number II -- LeetCode

    A strobogrammatic number is a number that looks the same when rotated 180 degrees (looked at upside ...

  10. rest ---hateoas

    推荐一篇博客. https://www.ibm.com/developerworks/cn/java/j-lo-SpringHATEOAS/