/*

 * 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. Java反射常用API汇总

    “JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方法和属性” 一.类对象的获取 1.通过对象获取 Object obj = ne ...

  2. UVA 10369 - Arctic NetWork (求最小生成树)

    题意: 在南极有  N  个科研站,要把这些站用卫星和无线电连接起来,是的任意两个之间都能互相通信,如果其中任意的一个地方安装了卫星,那么就可以和其他安装卫星的互相通信,和距离没有关系,但是安装无线电 ...

  3. Codeforces 757 E Bash Plays with Functions

    Discription Bash got tired on his journey to become the greatest Pokemon master. So he decides to ta ...

  4. 细说JavaScript对象(4): for in 循环

    如同 in 运算符一样,使用 for in 循环遍历对象属性时,也将往上遍历整个原型链. // Poisoning Object.prototype Object.prototype.bar = 1; ...

  5. MySQL索引,如何正确创建MySQL索引?

    索引可以提高数据的检索效率,也可以降低数据库的IO成本,并且索引还可以降低数据库的排序成本.排序分组操作主要消耗的就是CPU资源和内存,所以能够在排序分组操作中好好的利用索引将会极大地降低CPU资源的 ...

  6. JAVA实现通用日志记录

    原文:http://blog.csdn.net/jinzhencs/article/details/51882751 前言: 之前想在filter层直接过滤httpServerletRequest请求 ...

  7. 阅读 Android源码的一些姿势

    日常开发中怎么阅读源码 找到正确的源码 IDE 是日常经常用的东西,Eclipse 就不说了,直接从 Android Studio(基于 IntelliJ Community 版本改造)开始. 我们平 ...

  8. 粗谈CDN

    CDN:内容分发网络(content delivery network) 1.DNS解析到最快(有可能是地理上最近,也有可能是地理上远但是链路最好)的CDN缓存设备 2.从CDN获取已经缓存的资源 3 ...

  9. apache 的rewrite函数配置伪静态

    配置伪静态目的:对于访问比较长的uri,利于网站搜索工具更容易记住,换句话利于SEO 在配置文件中添加或找到 <IfModule mod_rewrite.c> </IfModule& ...

  10. 在CcentOS系统上将deb包转换为rpm包

    deb文件格式本是ubuntu/debian系统下的安装文件,那么我想要在redhat/centos/fedora中安装,需要把deb格式的软件包转化成rpm格式. 需要用到的转换工具:alien_8 ...