红黑数的性质这里就不多说了网上很多,主要看看nginx是如何定义的rbtree和怎么使用它
-
rbtree = ngx_slab_alloc(shpool, sizeof(ngx_rbtree_t));
-
-
sentinel = ngx_slab_alloc(shpool, sizeof(ngx_rbtree_node_t));
-
-
ngx_rbtree_init(ctx->rbtree, ctx->sentinel, ngx_http_srs_hook_rbtree_insert_value);
主要看下ngx_rbtree_init的实现:
-
#define ngx_rbtree_init(tree, s, i) \
-
ngx_rbtree_sentinel_init(s); \
-
(tree)->root = s; \
-
(tree)->sentinel = s; \
-
(tree)->insert = i
关键的就是参数i,这个是个函数指针,作为红黑树的插入节点时候的算法,这个需要用户自己实现
-
typedef void (*ngx_rbtree_insert_pt) (ngx_rbtree_node_t *root,
-
ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
第二个参数就是需要插入的节点数据,第三个参数是哨兵节点
接下去看下怎么实现这个插入函数(ps: nginx很多模块中已经有了rbtree插入的实现,我也是参考写的)
-
static void
-
ngx_http_srs_hook_rbtree_insert_value(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel) {
-
-
ngx_rbtree_node_t **p;
-
p = NULL;
-
if(node == NULL) {
-
return;
-
}
-
for ( ;; ) {
-
-
if (node->key < temp->key) {
-
-
p = &temp->left;
-
-
} else if (node->key > temp->key) {
-
-
p = &temp->right;
-
-
} else {
-
-
break;
-
}
-
-
if (*p == sentinel) {
-
break;
-
}
-
-
temp = *p;
-
}
-
-
*p = node;
-
node->parent = temp;
-
node->left = sentinel;
-
node->right = sentinel;
-
ngx_rbt_red(node);
-
-
}
对于使用者只需要负责插入的算法, 对于红黑数的反转等问题nginx都为大家做了
现在看看怎么进行节点的插入的
-
typedef struct{
-
ngx_rbtree_node_t node;
-
void *data;
-
}channel;
-
-
channel findchannel;
-
ngx_rbtree_insert(srshookctx->rbtree,&(findchannel->node));
看下ngx_rbtree_insert的实现:
-
ngx_rbtree_insert(ngx_rbtree_t *tree, ngx_rbtree_node_t *node)
-
{
-
ngx_rbtree_node_t **root, *temp, *sentinel;
-
-
-
-
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);
-
-
-
-
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);
-
}
这样红黑数的插入就完成了,那如何来查找树里的节点呢?这里我实现了一个查找节点的函数
-
static requestchannel_st*
-
ngx_http_channel_tree_lookup(ngx_http_srs_hook_ctx_t *srsctx, uint64_t key)
-
{
-
ngx_rbtree_key_t node_key;
-
ngx_rbtree_node_t *node;
-
ngx_rbtree_node_t *sentinel;
-
requestchannel_st *fcn;
-
-
node_key = key;
-
-
node = srsctx->rbtree->root;
-
sentinel = srsctx->rbtree->sentinel;
-
-
while (node != sentinel) {
-
-
if (node_key < node->key) {
-
node = node->left;
-
continue;
-
}
-
-
if (node_key > node->key) {
-
node = node->right;
-
continue;
-
}
-
-
-
-
fcn = (requestchannel_st *) node;
-
-
return fcn;
-
}
-
-
-
-
return NULL;
-
}
-
阅读(5305) | 评论(0) | 转发(0) |