Nginx源码解析 --红黑树
创始人
2024-02-18 00:44:31
0

预读知识

红黑树是一种自平衡二叉树,不仅可以使用二分法快速查找,而且插入和删除操作的效率也很高,常用于构造关联数组(例如C++标准库里的set和 map)。

在Nginx里红黑树主要用在事件机制里的定时器,检查连接超时,此外还在reslover、cache里用于快速查找。

 红黑树概要_编程界的谢菲尔德的博客-CSDN博客

  1. 节点不是黑色,就是红色(非黑即红)
  2. 根节点为黑色
  3. 叶节点为黑色(叶节点是指末梢的空节点 NilNull
  4. 一个节点为红色,则其两个子节点必须是黑色的(根到叶子的所有路径,不可能存在两个连续的红色节点)
  5. 每个节点到叶子节点的所有路径,都包含相同数目的黑色节点(相同的黑色高度)

基本数据结构

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;u_char                 color;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;ngx_rbtree_node_t     *sentinel;ngx_rbtree_insert_pt   insert;
};

结构定义

1.

typedef ngx_uint_t  ngx_rbtree_key_t;                 //无符号
typedef ngx_int_t   ngx_rbtree_key_int_t;           //有符号

2结点                                           //侵入容器

ngx_rbtree_key_t         key;       //红黑树的键 用于排序比较

 ngx_rbtree_node_t     *left;      //左指针
 ngx_rbtree_node_t     *right;    //右指针
 ngx_rbtree_node_t     *parent; //父结点
 u_char                          color;    // 1代表 0代表 黑色
 u_char                          data;     // 无意义

3 树                                            

 ngx_rbtree_node_t     *root;           //红黑树的根节点:           
 ngx_rbtree_node_t     *sentinel;     //红黑树的哨兵节点,用于简化实现,它总是黑色的;
 ngx_rbtree_insert_pt   insert;         //节点的插入方法,允许对特殊节点定制特殊插入方法

4. 内存布局

 

2.操作函数

1.初始化(红为一  黑为0 同时也代表 正负)


#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)#define ngx_rbtree_sentinel_init(node)  ngx_rbt_black(node)#define ngx_rbtree_init(tree, s, i)                                           \ngx_rbtree_sentinel_init(s);                                              \(tree)->root = s;                                                         \(tree)->sentinel = s;                                                     \(tree)->insert = i
ngx_rbtree_init实际上是一个宏,初始化后红黑树里仅有一个哨兵节点s,它同时也是根节点。

2.辅助函数 (旋转函数)(个人建议 直接看红黑树概要_编程界的谢菲尔德的博客-CSDN博客

1.左旋

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;temp = node->right;node->right = temp->left;if (temp->left != sentinel) {temp->left->parent = node;}temp->parent = node->parent;if (node == *root) {*root = temp;} else if (node == node->parent->left) {node->parent->left = temp;} else {node->parent->right = temp;}temp->left = node;node->parent = temp;
}

2.右旋

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;
}

3.删除

void
ngx_rbtree_delete(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 = &tree->root;sentinel = tree->sentinel;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;}}
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);if (subst == subst->parent->left) {subst->parent->left = temp;} else {subst->parent->right = temp;}if (subst == node) {temp->parent = subst->parent;} else {if (subst->parent == node) {temp->parent = subst;} else {temp->parent = subst->parent;}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;}}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;}
.....

4.插入

1.首先包装一个整的

ngx_rbtree_insert(ngx_rbtree_t *tree, ngx_rbtree_node_t *node)

2.分类

2.1void  ngx_rbtree_insert_value(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node,
    ngx_rbtree_node_t *sentinel)    //这个是一个数值插入

2.2 void ngx_rbtree_insert_timer_value(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node,
    ngx_rbtree_node_t *sentinel)    定时器红黑树的专用插入函数,键值是毫秒值

2.3 (字符串头文件里)

void ngx str_rbtree_insert_value ngx_rbtree_node_t *temp ,

ngx_rbtree_node_t *node , ngx_rbtree_node_t *sentinel); //字符串红黑树的专用插入函数,键值是字符串的hash值



 

相关内容

热门资讯

公司股东与妻子分居期间出轨女下... 近日据报道,宁夏永宁县人民法院一审查明公司股东李某乙在与妻子李某甲分居期间,与公司女员工马某某存在不...
动物学家、律师和创作者,Thi... 12月21日,以“一起·了不起”为主题的2025 ThinkPad黑FUN礼在京举办。活动现场,律师...
徐奇渊:扩内需与对外政策紧密相... 近日,中国海关总署发布了一组数据令人关注:2025年前11个月,我国货物贸易顺差达到1.08万亿美元...
46岁上海独居女子不幸离世,官... 居住在上海虹口区46岁的蒋女士因突发脑溢血于今年10月入院,远亲吴先生与其公司共同垫付了医药费,但她...
威海市汽车以旧换新补贴政策调整... 根据稳妥有序开展消费品以旧换新工作统一部署,经研究决定,对我市汽车以旧换新补贴政策进行调整。现将有关...
动物学家、律师、创作者都pic... 12月21日,在2025 ThinkPad黑FUN礼现场,三名专业领域用户用真实案例诠释了Think...
从拒赔到和解:涉外货运保险理赔... 近日,国家金融监管总局、最高人民法院遴选出6个具有典型性、示范性的金融领域纠纷多元化解案例,12月1...
湖北大冶一男子当街拦车砸玻璃,... 大象新闻2025-12-21 16:21:41 12月20日,湖北大冶市网民发视频称,一名男子在新冶...
韩媒曝尹锡悦夫妇下周将被同时起... 据韩联社21日报道,负责调查韩国前总统尹锡悦夫人金建希弊案的独立检察组(独检组)将于下周同时对尹锡悦...
大冶一男子拦停轿车打砸!大冶公... 原标题:大冶公安查处一起妨碍交通工具正常行驶案件 2025年12月20日15时许,我辖区居民刘某(男...