nginx--rbtree使用详解
来源:互联网 发布:js截取字符串的方法 编辑:程序博客网 时间:2024/05/02 01:54
红黑数的性质这里就不多说了网上很多,主要看看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 { /* node->key == temp->key */ break; //目前的实现不支持相同的key的节点 } 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; /* 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 */ //数据插入之后, nginx就为我们做了很复杂的红黑树的翻转来保持树的平衡 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) { //通过左右子树查找key一样的节点 node = node->left; continue; } if (node_key > node->key) { node = node->right; continue; } /* node_key == node->key */ fcn = (requestchannel_st *) node; //找到节点就转成节点数据结构,返回 return fcn; } /* not found */ return NULL;}
0 0
- nginx--rbtree使用详解
- 6.Nginx红黑树rbtree
- 内核rbtree使用示例
- RBTree
- RBTree
- RBTree
- RBTree
- RBTree
- rbtree
- rbtree
- RBTree
- 红黑树rbtree实现,原汁原味nginx。加深理解!
- 使用内核数据结构:红黑树 rbtree
- rbtree原理及应用--使用
- linux内核分析之rbtree的使用
- Linux内核中rbtree的使用
- linux内核分析之rbtree的使用
- Nginx 配置文件Nginx.conf变量使用详解
- DOM4J方式解析、创建XML文件(实例)
- PowerSinger之Java环境配制
- 第10周项目1-二叉树算法库
- 在Android中通过Intent使用Bundle传递对象
- 深入了解UART
- nginx--rbtree使用详解
- 第11周项目1 验证算法(2)二叉树构造算法的验证
- 二分图——图的割点
- win10 开机自动启动安装进度命令框禁止加载
- EvnetBus3.0的使用
- 第十一周项目1—层次遍历的算法
- [BZOJ1293][SCOI2009]生日礼物(单调队列)
- 第十一周项目1-(1)层次遍历的验证
- PTA 4-3 Add Two Polynomials