myttree.c
来自「sourceforge历史版本完整下载: http://sourceforge.」· C语言 代码 · 共 1,132 行 · 第 1/2 页
C
1,132 行
/** * * @file myTTree.c T树 * * @author lin shao chuan (email:lsccsl@tom.com, msn:lsccsl@163.net) * * @brief * T 树是avl树的扩展(或者说是avl树与b树综合的产物) * 即一个node包含一个关键字数组. * 数组里的关键字已经被排好序 * oracle ten times, fastdb, mysql cluster等,使用了T树做为索引. * * 添加关键字至T树 * 从根节点开始找寻,如果能找到bound数组,则添加,如果数组已满,抽出最小的那一个元素A. * 行进至greate lower bound(左子树最靠右的那个节点),如果可以添加A,则添加 * 如果不能,则应创建新节点,并且根据实际情况旋转树保证avl树的平衡 * * 如果没有找到合适的节点,则在最右(左)添加,添加不了则创建新节点,并根据实际情况旋转树 * * 删除关键字 * 从根节点开始找寻,如果找到 * a 如果当前节点的个数在删除之后仍然大于下限,操作完成 * b 如果当前节点个数小于小限,并且是内部节点,则从greate lower bound节点中借 * 如果greate lower bound节点是leaf节点 同c * 如果greate lower bound节点是half leaf节点 同d * * c 如果是half leaf节点,判断是否可以合并,然后根据需要旋转树 * d 如果是leaf节点,判断是否要删除,然后根据需要旋转树 * * 关于数组排序: * fastDB与mysql使用的都是二分查找定位排序 */#include "myTTree.h"#include <assert.h>#include <string.h>#include <stdio.h>#include "__avl_tree.h"#include "myvector.h"#include "__vector_inter.h"#include "__bstree.h"typedef struct __myttree_key_t_{ /* * 数组,存放索引信息 */ HMYVECTOR hv_index;}myttree_key_t;typedef struct __myttree_node_t_{ /* * avl平衡树节点 */ __avltree_node_t avl_node; myttree_key_t key;}myttree_node_t;typedef struct __myttree_t_{ HMYMEMPOOL hm; ALG_COMPARE compare; void * context; /* * T树的根节点 */ myttree_node_t * root; /* * 一个节点的关键字个数下限 */ size_t underflow; /* * 一个节点的关键个数上限 */ size_t overflow;}myttree_t;/** * 索引数组排序 */#define ttree_sort_index_array(ttree, hv_index) do{\ MyAlgQuickSort(__vector_inter_get_array((hv_index)),\ __vector_inter_get_count((hv_index)), \ __vector_inter_get_array_step_size((hv_index)),\ ttree_compare, NULL, NULL, NULL, ttree, NULL, 0);\ }while(0)/** * T树比较 */static __INLINE__ int ttree_compare(const void * data1, const void * data2, const void * context){ HMYVECTOR_ITER it1 = *((HMYVECTOR_ITER *)data1); HMYVECTOR_ITER it2 = *((HMYVECTOR_ITER *)data2); myttree_t * ttree = (myttree_t *)context; assert(ttree && it1 && it2 && ttree->compare); return ttree->compare(__vector_inter_get_iter_data(it1), __vector_inter_get_iter_data(it2), ttree->context);}/** * 索引数组查找 */static __INLINE__ int ttree_search(myttree_t * ttree, HMYVECTOR hv_index, const void * index_info, size_t * index){ assert(ttree && hv_index && index_info); { __vector_inter_get_temp_it(it, 0, (void *)index_info); return MyBinarySearch1(__vector_inter_get_array(hv_index), __vector_inter_get_count(hv_index), __vector_inter_get_array_step_size(hv_index), &it, ttree_compare, index, ttree); }}/** * 创建一个T树节点 */static __INLINE__ myttree_node_t * ttree_create_node(myttree_t * ttree, myttree_node_t * parent){ myttree_node_t * node = (myttree_node_t *)MyMemPoolMalloc((assert(ttree), ttree->hm), sizeof(*node)); if(NULL == node) return NULL; memset(node, 0, sizeof(*node)); node->key.hv_index = __vector_inter_create(ttree->hm, ttree->overflow + 1, NULL, NULL); node->avl_node.height = 1; node->avl_node.base.parent = (bstree_node_t *)parent; return node;}/** * 销毁一个T树节点 */static __INLINE__ void ttree_destroy_node(myttree_t * ttree, myttree_node_t * node){ assert(ttree && node && node->key.hv_index); __vector_inter_destroy(node->key.hv_index); MyMemPoolFree(ttree->hm, node);}/** * @brief 描述在__bstree_erase函数中如何释放每个节点 * @param context:用户的上下文数据 * @param root:根节点 */static void __ttree_destroy_node_cb(void * context, bstree_node_t * root){ ttree_destroy_node((myttree_t *)context, (myttree_node_t *)root);}/** * @brief 查找合适的节点位置 */static __INLINE__ myttree_node_t * ttree_search_bound(myttree_t * ttree, myttree_node_t * node, const void * key, myttree_node_t ** parent){ HMYVECTOR_ITER it_first = NULL; HMYVECTOR_ITER it_last = NULL; assert(ttree && ttree->compare && parent); while(node) { HMYVECTOR hv = node->key.hv_index; assert(__vector_inter_get_count(hv)); *parent = node; it_first = __vector_get_head(hv); it_last = __vector_get_tail(hv); if(ttree->compare(key, __vector_inter_get_iter_data(it_first), ttree->context) < 0) { node = (myttree_node_t *)node->avl_node.base.left; continue; } if(ttree->compare(key, __vector_inter_get_iter_data(it_last), ttree->context) > 0) { node = (myttree_node_t *)node->avl_node.base.right; continue; } return node; } return NULL;}/** * @brief 在叶节点处添加 */static __INLINE__ int ttree_add_leaf(myttree_t * ttree, myttree_node_t * current_node, const void * index_info){ HMYVECTOR hv_index = NULL; assert(ttree && current_node && ttree->compare); assert(NULL == current_node->avl_node.base.right && NULL == current_node->avl_node.base.left); hv_index = current_node->key.hv_index; assert(hv_index && hv_index->el_array && hv_index->el_array_size); /* * 如果没有上溢 */ if(__vector_inter_get_count(hv_index) < ttree->overflow) { /* * 在合适的位置添加 * todo:看了其它开源的T树实现,实际上它们不是这么做的,直接将数据插到合适的位置. */ __vector_inter_add(hv_index, index_info, 0); ttree_sort_index_array(ttree, hv_index); return 0; } else { myttree_node_t * node = ttree_create_node(ttree, current_node); if(NULL == node) return -1; current_node->avl_node.base.right = (bstree_node_t *)node; /* * 在合适的位置添加 * todo:看了其它开源的T树实现,实际上它们不是这么做的,直接将数据插到合适的位置. */ __vector_inter_add(hv_index, index_info, 0); ttree_sort_index_array(ttree, hv_index); /* * 添加了节点,旋转树平衡 * 在旋转之前,需要对当前树的形状进行判断,调整元素数组,防止inter 节点出现underflow的情况 * * 情形1 情形2(与情形1为镜像) * A A * / \ * B B * \ / * C C * 此时需要所B中数组搬给C,防止出现C的节点underflow,因为旋转后,C将成为inter,如下图 * C C * / \ 或者 / \ * B A A B * * 在本例中,由于C必为B右节点,所以只考虑情形1,情形2在本例中是不可能出现的 */ if(current_node->avl_node.base.parent) { /* 如果树的形状为情形1 */ if((bstree_node_t *)current_node == current_node->avl_node.base.parent->left && NULL == current_node->avl_node.base.parent->right) { /* * 把B中的元素借为C * 将B中的最小元素借给C * B C互换元素数组 */ __vector_inter_add(node->key.hv_index, __vector_get_head_data(hv_index), 0); __vector_inter_del(hv_index, 0); current_node->key.hv_index = node->key.hv_index; node->key.hv_index = hv_index; } else { /* * 节点上溢了 * 取出最大节点node_max,node_max成为新右分支,并旋转树 */ __vector_inter_add(node->key.hv_index, __vector_get_tail_data(hv_index), 0); __vector_inter_del(hv_index, __vector_inter_get_count(hv_index) - 1); } } else { /* * 节点上溢了 * 取出最大节点node_max,node_max成为新右分支,并旋转树 */ __vector_inter_add(node->key.hv_index, __vector_get_tail_data(hv_index), 0); __vector_inter_del(hv_index, __vector_inter_get_count(hv_index) - 1); } __avltree_balance((__avltree_node_t **)&ttree->root, (__avltree_node_t *)current_node); return 0; }}/** * @brief 在半叶节点添加 */static __INLINE__ int ttree_add_half_leaf(myttree_t * ttree, myttree_node_t * current_node, const void * index_info){ HMYVECTOR hv_index = NULL; assert(ttree && current_node && ttree->compare); assert(NULL == current_node->avl_node.base.left || NULL == current_node->avl_node.base.right); assert(current_node->avl_node.base.left || current_node->avl_node.base.right); /* * 如果是半叶节点 * 区分左右子树的情况 * 如果只有左子树,取出最大节点成为新分支 * 如果只有右子树,取出最大节点成为新分支 ttree_add(left, max_index_info) */ hv_index = current_node->key.hv_index; assert(hv_index && hv_index->el_array && hv_index->el_count && hv_index->el_array_size); if(__vector_inter_get_count(hv_index) < ttree->overflow) { /* * 没有上溢 * 在合适的位置添加 * todo:看了其它开源的T树实现,实际上它们不是这么做的,直接将数据插到合适的位置. */ __vector_inter_add(hv_index, index_info, 0); ttree_sort_index_array(ttree, hv_index); return 0; } else { if(current_node->avl_node.base.left) { myttree_node_t * node = ttree_create_node(ttree, current_node); if(NULL == node) return -1; /* 根据逻辑,这个条件必成立 */ assert(NULL == current_node->avl_node.base.right); /* * 添加了节点,但是根据逻辑得出,此时是不需要旋转树的 */ current_node->avl_node.base.right = (bstree_node_t *)node; /* * 上溢 * 在合适的位置添加 * todo:看了其它开源的T树实现,实际上它们不是这么做的,直接将数据插到合适的位置. */ __vector_inter_add(hv_index, index_info, 0); ttree_sort_index_array(ttree, hv_index); __vector_inter_add(node->key.hv_index, __vector_get_tail_data(hv_index), 0); __vector_inter_del(hv_index, __vector_inter_get_count(hv_index) - 1); return 0; } else { /* * 上溢 * 在合适的位置添加 * todo:看了其它开源的T树实现,实际上它们不是这么做的,直接将数据插到合适的位置. */ __vector_inter_add(hv_index, index_info, 0); ttree_sort_index_array(ttree, hv_index); /* 根据逻辑,这个条件必成立 */ assert(current_node->avl_node.base.right); assert(NULL == current_node->avl_node.base.right->left && NULL == current_node->avl_node.base.right->right); { int ret = ttree_add_leaf(ttree, (myttree_node_t *)(current_node->avl_node.base.right), __vector_get_tail_data(hv_index)); assert(ret == 0); } __vector_inter_del(hv_index, __vector_inter_get_count(hv_index) - 1); return 0; } }}/** * @brief 在内部节点添加 */static __INLINE__ int ttree_add_inter(myttree_t * ttree, myttree_node_t * current_node, const void * index_info){ HMYVECTOR hv_index = NULL; assert(ttree && current_node && ttree->compare); assert(current_node->avl_node.base.left && current_node->avl_node.base.right); hv_index = current_node->key.hv_index; assert(hv_index && hv_index->el_array && hv_index->el_array_size && hv_index->el_count); if(__vector_inter_get_count(hv_index) < ttree->overflow) { /* * 没有上溢 * 在合适的位置添加 * todo:看了其它开源的T树实现,实际上它们不是这么做的,直接将数据插到合适的位置. */ __vector_inter_add(hv_index, index_info, 0); ttree_sort_index_array(ttree, hv_index); return 0; } else { /* least upper bound */ myttree_node_t * lub_node = NULL; /* * 上溢 * 在合适的位置添加 * todo:看了其它开源的T树实现,实际上它们不是这么做的,直接将数据插到合适的位置. */ void * ii = NULL; __vector_inter_add(hv_index, index_info, 0); ttree_sort_index_array(ttree, hv_index); ii = __vector_get_tail_data(hv_index); __vector_inter_del(hv_index, __vector_inter_get_count(hv_index) - 1); /* * 如果出现上溢,取出最大节点,ttree_add(right, max_key); * 加入到least upper bound节点里 */ lub_node = (myttree_node_t *)current_node->avl_node.base.right; assert(lub_node); while(lub_node->avl_node.base.left) lub_node = (myttree_node_t *)lub_node->avl_node.base.left; if(lub_node->avl_node.base.right) { int ret = ttree_add_half_leaf(ttree, lub_node, ii); assert(0 == ret); } else { int ret = ttree_add_leaf(ttree, lub_node, ii); assert(0 == ret); } return 0; }}/** * @brief 添加节点 */static __INLINE__ int ttree_add(myttree_t * ttree, const void * index_info){ myttree_node_t * parent = NULL; myttree_node_t * node = NULL; assert(ttree && ttree->root && ttree->compare); /* * 寻找bound node */ if(ttree->root->avl_node.base.left || ttree->root->avl_node.base.right) node = ttree_search_bound(ttree, ttree->root, index_info, &parent); else node = ttree->root; if(node) { /* * 如果找到 */ HMYVECTOR hv_index = node->key.hv_index; size_t index = 0; /* * 如果在节点中找到关键字,添加失败,并返回 */ if(0 == ttree_search(ttree, hv_index, index_info, &index)) return -1; if(NULL == node->avl_node.base.left && NULL == node->avl_node.base.right) { /* * 在叶节点处添加 */ return ttree_add_leaf(ttree, node, index_info); } else if(NULL != node->avl_node.base.left && NULL != node->avl_node.base.right) { /* * 在内部节点添加 */ return ttree_add_inter(ttree, node, index_info); } else { /* * 在半叶节点处添加 */ return ttree_add_half_leaf(ttree, node, index_info); } } assert(parent); assert(NULL == parent->avl_node.base.left || NULL == parent->avl_node.base.right); if(NULL == parent->avl_node.base.left && NULL == parent->avl_node.base.right) { /* * 在叶节点添加 */ return ttree_add_leaf(ttree, parent, index_info); } else { /* * 在半叶节点添加 */ return ttree_add_half_leaf(ttree, parent, index_info); }}/** * @brief 在叶节点处删除 */static __INLINE__ int ttree_del_leaf(myttree_t * ttree, myttree_node_t * current_node, size_t index){ HMYVECTOR hv_index = NULL; assert(ttree && current_node && (current_node->avl_node.base.parent || current_node == ttree->root)); assert(NULL == current_node->avl_node.base.left && NULL == current_node->avl_node.base.right); hv_index = current_node->key.hv_index; __vector_inter_del(hv_index, index);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?