Nginx学习笔记(十):基数树
2014-02-06 18:51
134 查看
前言
接上篇。。。基数树ngx_radix_tree_t
基数树也是一种二叉查找树,它要求存储的每个节点必须以32位整型作为任意两节点的唯一标识。另外,基数树与红黑树不同的一点:ngx_radix_tree_t会负责分配每个节点占用的内存。也因为这一点,基数树不像红黑树灵活,目前在Nginx中应用不广泛。基数树原理
基数树具备二叉查找树所有优点,并且不用像红黑树通过自身旋转达到平衡,基数树不用管树的形态是否平衡。也因此,它在插入节点、删除节点的速度会比红黑树快的多。为什么基数树可以不管树是否平衡?
首先,红黑树是通过不同节点key关键字的比较决定树的形态,而基数树的每个节点的key关键字自身已经决定了其在树中的位置。
具体决定方法:
先将节点的key关键字转化为二进制,32位,从左至右开始,遇0入左子树,遇1入右子树。这样,ngx_radix_tree_t树的最大深度为32。另外,为了减少树的高度,基数树中有掩码的概念。
e.g.
掩码为0xE0000000(十六进制表32位)时,即表示树的高度为3。
如果此时一个节点的key关键字为0x0FFFFFFF,那么由于掩码的存在,实际上只有前3位有效,该节点的实际的key关键字为0x00000000;
如果此时一个节点的key关键字为0x20000000,根据掩码决定取其转化为二进制后的前3位为010,因此,该节点的位置是,根节点-->左子树-->右子树-->左子树。用下图至关表示下:
与红黑树不同,红黑树节点不负责分配每个树节点的内存,基数树则负责分配,如下是基数树数据结构:
typedef struct { /* 基数树根节点 */ ngx_radix_node_t *root; /* 内存池,负责基数树节点分配 */ ngx_pool_t *pool; /* 管理已分配内存,但未使用的节点,这些节点实际上会组成一单链表 */ ngx_radix_node_t *free; /* 已分配内存中还未使用内存的首地址 */ char *start; /* 已分配内存中还未使用内存的大小 */ size_t size; } ngx_radix_tree_t;其中,需要注意的是,在每次删除一个树节点时,并不释放节点的内存,还是将其放入free指向的单链表中。这样在添加节点时,则首先查看free链表中时候有节点,如果有则优先使用,如果没有则再从内存池pool处分配。
对基数树的操作也就是创建、删除等常规。这里因为基数树本身用的就不多,暂时对这个东西就只做了解了。
总结
基数树为每个节点分配内存,以32位整型关键字作为唯一标识,每个关键字都决定在树种的位置。此外,加入掩码决定基数树的高度。删除节点不作内存释放,而是加入空闲链表,以供后续使用。主要参考
《深入理解Nginx》相关文章推荐
- 上海市历年(补充)住房公积金缴存基数、比例、上下限一览表
- 稳定排序之基数排序
- 计数排序,基数排序,桶排序算法
- 各进制基数、符号及示例
- 采用回调函数的内部排序算法-插入排序,希尔排序,冒泡,快排,堆排,归并排,基数排序
- 基数排序
- 手机号码查找算法(基数树)
- 基数排序
- 基数排序简要演示
- 从MySQL中获得数据表auto_increment值(基数)的方法
- 基数排序 计数排序 桶排序
- (1)oracle单表选择率(selectivity)——计算执行计划的基数
- 【11g新特性】Cardinality Feedback基数反馈
- 《算法导论》第12章 二叉查找树 (3)基数树(转)
- Nginx学习笔记(七) 创建子进程
- 基数排序
- 基数排序
- PowerDesigner 15设置mysql主键自动增长及基数
- 排序算法系列-堆排序-快速排序-基数排序-简单选择排序-归并排序
- UVa 10608 Friends (求并查集中最大的集合的基数)