/*

 * 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. Python3在Windows安装配置及简单试用

    1,安装配置 安装版本是Python3.5,我的安装路径是E:\ImProgram\Python35 添加环境变量,将上述路径加入到path中 这样cmd打开命令窗口,输入python就能看到调用成功 ...

  2. springBoot Feign Hystrix

    1.引入依赖包 <!-- 引入关于 hystrix的依赖 --> <dependency> <groupId>org.springframework.cloud&l ...

  3. (分享别人的一篇好文章,来自jackson0714)30分钟全面解析-SQL事务+隔离级别+阻塞+死锁()

    30分钟全面解析-SQL事务+隔离级别+阻塞+死锁 阅读目录 概述: 一.事务 二.锁 三.阻塞 四.隔离级别 五.死锁 以前总是追求新东西,发现基础才是最重要的,今年主要的目标是精通SQL查询和SQ ...

  4. bzoj 3462: DZY Loves Math II

    3462: DZY Loves Math II Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 211  Solved: 103[Submit][Sta ...

  5. [LOJ6208]树上询问

    题目大意: 有一棵n节点的树,根为1号节点.每个节点有两个权值ki,ti,初始值均为0. 给出三种操作: 1.Add(x,d)操作:将x到根的路径上所有点的ki←ki+d 2.Mul(x,d)操作:将 ...

  6. jQuery滑动方法

    jQuery 滑动方法 通过 jQuery,您可以在元素上创建滑动效果. jQuery 拥有以下滑动方法: slideDown() slideUp() slideToggle() jQuery sli ...

  7. 【NOIP模拟赛】【乱搞AC】【贪心】【模拟】匹配

    匹配 (match.pas/match.c/match.cpp) [题目描述] 到了新的学期,Mcx痛苦的发现通用技术课居然是有实验课的,这样的话他就不得不放弃写作业的想法而去做一件类似于搭积木的事情 ...

  8. 链接服务器 "(null)" 的 OLE DB 访问接口 "SQLNCLI11" 指示该对象没有列,或当前用户没有访问该对象的权限。

    原文:链接服务器 "(null)" 的 OLE DB 访问接口 "SQLNCLI11" 指示该对象没有列,或当前用户没有访问该对象的权限. SELECT * F ...

  9. 利用Yum彻底移除docker

    yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-la ...

  10. numpy自动生成数组

    1 np.arange(),类似于range,通过指定开始值,终值和步长来创建表示等差数列的一维数组,注意该函数和range一样结果不包含终值. >>> np.arange(10) ...