/*

 * 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. [BZOJ1070][SCOI2007]修车 费用流

    1070: [SCOI2007]修车 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 6209  Solved: 2641[Submit][Status] ...

  2. 在windows 10 64bit系统上安装python 3.6 64bit的numpy模块

    1.查找自己的python版本对照的whl文件(cp36代表的是版本) 地址:https://pypi.python.org/pypi/numpy 2.下载完毕执行一下命令即可 pip install ...

  3. 【NOIP模拟赛】【乱搞AC】【奇技淫巧】【乘法原理】回文串计数

    回文串计数 (calc.pas/calc.c/calc.cpp) [题目描述] 虽然是一名理科生,Mcx常常声称自己是一名真正的文科生.不知为何,他对于背诵总有一种莫名的热爱,这也促使他走向了以记忆量 ...

  4. 【报错】spring boot启动 报错 找不到实体类Not a managed type: class com.pisen.cloud.luna.feign.ten.beans.SysUser

    Caused by: java.lang.IllegalArgumentException: Not a managed type: class com.pisen.cloud.luna.feign. ...

  5. Go -- 读取文件内容

    Golang 的文件读取方法很多,刚上手时不知道怎么选择,所以贴在此处便后速查. 一次性读取 小文件推荐一次性读取,这样程序更简单,而且速度最快. 代码如下: func ReadAll(filePth ...

  6. 设计模式之工厂模式之抽象工厂(php实现)

    github地址: git@github.com:ZQCard/design_pattern.git 抽象工厂模式: 先来认识下什么是产品族: 位于不同产品等级结构中,功能相关联的产品组成的家族.图中 ...

  7. git回退到某个commit

    git log查看提交历史及提交的commit_id 回退命令: $ git reset --hard HEAD^ 回退到上个版本$ git reset --hard HEAD~3 回退到前3次提交之 ...

  8. 用DotSpatial下载谷歌瓦片图并展示到地图控件上 【转】

    http://blog.csdn.net/caoshiying/article/details/51991647 上一篇文章讲解如何加载各地图的WMS地图服务.虽然不涉及到瓦片,但是每次地图刷新都要请 ...

  9. 【LeetCode-面试算法经典-Java实现】【109-Convert Sorted List to Binary Search Tree(排序链表转换成二叉排序树)】

    [109-Convert Sorted List to Binary Search Tree(排序链表转换成二叉排序树)] [LeetCode-面试算法经典-Java实现][全部题目文件夹索引] 原题 ...

  10. 模拟服务器MockServer之Moco详细介绍

    转载:http://blog.csdn.net/vite_s/article/details/54583243 前面一篇介绍了如何用mockito来测试我们的一些异步任务,例如网络请求时候的异步回调. ...