Nginx的定时器管理借助红黑树来完成,红黑树这种数据结构在很多开源项目中被广泛使用。
红黑树是一种自平衡二叉搜索树,可以在O(log n)时间内做查找、插入和删除,这里n是树中元素的数目。
红黑树是每个节点都带有颜色属性的二叉搜索数,颜色为红色或黑色。在二叉搜索树的一般要求以外,它还有以下的额外要求:
(1)节点是红色或黑色
(2)根节点是黑色的
(3)所有叶子都是黑色(叶子是NIL节点)
(4)每个红色节点必须有两个黑色的子节点
(5)从任一节点到其每个叶子的所有简单路径都包含相同数目的黑色节点
/*core/ngx_rbtree.h */
typedef struct ngx_rbtree_s ngx_rbtree_t;
// rbtree节点结构体
struct ngx_rbtree_s {
ngx_int_t key; //节点值
ngx_rbtree_t *left; //左子节点
ngx_rbtree_t *right; //右子节点
ngx_rbtree_t *parent; //父节点
char color; //颜色
};
/*
rbtree获取值最小的节点
param node: 根节点指针的指针
sentinel: 作为哨兵的NIL节点指针
*/
ngx_inline static ngx_rbtree_t *ngx_rbtree_min(ngx_rbtree_t *node,
ngx_rbtree_t *sentinel)
{
// 二叉搜索数: 节点的左子树的值都比其小
// 那么只需要找到最左侧的节点即为最小节点
while (node->left != sentinel) {
node = node->left;
}
return node;
}
/*core/ngx_rbtree.c */
/*
rbtree左旋调整
param root: 根节点指针的指针
sentinel: 作为哨兵的NIL节点指针
node: 作为旋转基点的节点指针
*/
ngx_inline void ngx_rbtree_left_rotate(ngx_rbtree_t **root,
ngx_rbtree_t *sentinel,
ngx_rbtree_t *node)
{
ngx_rbtree_t *temp;
temp = node->right; // temp指向node的右子节点
node->right = temp->left; // 让node的右子节点的左孩子成为node的右孩子
if (temp->left != sentinel) { // 如果node的原右子节点的左孩子不为空,
temp->left->parent = node; // 那么修改其父亲为node
}
temp->parent = node->parent; // 修改node的原右子节点的父亲为node的父亲
if (node == *root) { // 如果node为根节点,
*root = temp; // 那么新的根节点为node的原右子节点
} else if (node == node->parent->left) { // 如果node是其父亲的左孩子,
node->parent->left = temp; // 那么修改node的父亲的左孩子为node的原右子节点
} else { // 如果node是其父亲的右孩子,
node->parent->right = temp; // 那么修改node的父亲的右孩子为node的原右子节点
}
temp->left = node; // 修改node的原右子节点的左孩子为node
node->parent = temp; // 修改node的父亲为其原右子节点
}
/*
rbtree右旋调整
param root: 根节点指针的指针
sentinel: 作为哨兵的NIL节点指针
node: 作为旋转基点的节点指针
*/
ngx_inline void ngx_rbtree_right_rotate(ngx_rbtree_t **root,
ngx_rbtree_t *sentinel,
ngx_