B+树的重要性不用多说,Mysql的存储引擎就是使用的B+树,下面给出B+树的源码实现。
推荐一个有更多数据结构源码的Github地址:
https://github.com/0voice/algorithm-structure
包括(红黑树,B树,B*树,AVL树,BST树,完全二叉树,伸展树,LSM 树,哈夫曼树,2-3-4树,深度优先搜索,广度优先搜索,宽度优先搜索,费列数列,布隆过滤器,RSA加密算法,回溯算法,递归算法,分治算法,贪心算法,KMP算法,剪枝算法,滑动窗口算法,朴素贝叶斯算法,动态规划算法)等源码。
#include <stdlib.h> #include <stdio.h> #include <time.h> #include <string.h> #include <stdarg.h> #include <unistd.h> #include <fcntl.h> #include "btree.h" #define log_debug(msg,...) printf(msg, ##__VA_ARGS__) #define log_info(msg,...) printf(msg, ##__VA_ARGS__) #define new(type, num) (malloc(sizeof(type)*(num))) #define del(ptr) {if(NULL != ptr)free(ptr);} static inline void equal_divi(int value, int num, int * arry){ if(NULL == arry) return; int n = value/num; int i = 0; for(i=0; i num; i++){ arry[i] = n; } for(i=0; ivalue%num; i++){ arry[i]++; } } btnode_t * bt_new_node(btype_t type){ int size = 0; btnode_t * pNode = (btnode_t *)new(char, NODE_SIZE); if(NULL == pNode){ log_debug("Malloc new Node for B+Tree failed, please check!\n"); return NULL; } memset(pNode, 0, NODE_SIZE); pNode->bn_type = type; if(TYPE_LEAF == type){ pNode->bn_leaf.lnode.next = NULL; pNode->bn_leaf.lnode.prev = NULL; } return pNode; } void bt_free_node(btp_t ptr){ del(ptr.bn_ptr); } int bt_key_cmp(btk_t key1, btk_t key2){ if(key1.bn_key > key2.bn_key) return 1; else if(key1.bn_key == key2.bn_key) return 0; else return -1; } static inline btk_t bt_maxkey(btnode_t * pNode){ if(TYPE_INT == pNode->bn_type){ return pNode->bn_inter.bn_entry[pNode->bn_inter.bn_num-1].bn_key; } else{ return pNode->bn_leaf.bn_data[pNode->bn_leaf.bn_num-1]; } } static inline int bt_keynum(btnode_t * pNode){ if(TYPE_INT == pNode->bn_type){ return pNode->bn_inter.bn_num; } else{ return pNode->bn_leaf.bn_num; } } int bt_search_branch(btnode_t * pNode, btk_t key){ int i; for(i=0; ipNode->bn_inter.bn_num; i++){ if(bt_key_cmp(pNode->bn_inter.bn_entry[i].bn_key, key)0) continue; else return i; } return BTREE_FAIL; } int bt_search_leaf(btnode_t * pNode, btk_t key){ int i; for(i=0; ipNode->bn_leaf.bn_num; i++){ if(bt_key_cmp(pNode->bn_leaf.bn_data[i], key)0) continue; else return i; } return BTREE_FAIL; } int bt_exactsearch_leaf(btnode_t * pNode, btk_t key){ int i; for(i=0; ipNode->bn_leaf.bn_num; i++){ if(bt_key_cmp(pNode->bn_leaf.bn_data[i], key) != 0) continue; else return i; } return BTREE_FAIL; } int bt_branch_real_add(btinter_t * pinter, bti_t idx){ bti_t * tmpidxs = pinter->bn_entry; int i,j; for(i=0; ipinter->bn_num; i++){ if(bt_key_cmp(idx.bn_key, tmpidxs[i].bn_key)>0) continue; else{ break; } } for(j=pinter->bn_num; j>i; j--){ tmpidxs[j] = tmpidxs[j-1]; } tmpidxs[i] = idx; pinter->bn_num++; return BTREE_OK; } static inline int bt_branch_split(btnode_t * pNode, btnode_t ** ppNewNode){ if(INTER_KEY_NUM > pNode->bn_inter.bn_num){ log_debug("The leaf no need split!\n"); return BTREE_FAIL; } btnode_t * ptmp = bt_new_node(TYPE_INT); if(NULL == ptmp) return BTREE_FAIL; ptmp->bn_level = pNode->bn_level; ptmp->bn_type = TYPE_INT; memcpy(ptmp->bn_inter.bn_entry, pNode->bn_inter.bn_entry+INTER_KEY_NUM/2, sizeof(bti_t)*(INTER_KEY_NUM-INTER_KEY_NUM/2)); pNode->bn_inter.bn_num = INTER_KEY_NUM/2; ptmp->bn_inter.bn_num = INTER_KEY_NUM-INTER_KEY_NUM/2; *ppNewNode = ptmp; return BTREE_OK; } modv_t bt_branch_add(btnode_t * pNode, modinfo_t * pinfo){ if(pNode->bn_inter.bn_num == INTER_KEY_NUM){ btnode_t * pnewNode = NULL; if(BTREE_FAIL == bt_branch_split(pNode, &pnewNode)){ return MOD_FAIL; } if(NULL == pnewNode){ return MOD_FAIL; } int ret = bt_key_cmp(pNode->bn_inter.bn_entry[pNode->bn_inter.bn_num-1].bn_key, pinfo->newnode.bn_key); if(ret > 0){ bt_branch_real_add(&pNode->bn_inter, pinfo->newnode); } else{ bt_branch_real_add(&pnewNode->bn_inter, pinfo->newnode); } pinfo->midkey = 1; pinfo->newnode.bn_key = pnewNode->bn_inter.bn_entry[pnewNode->bn_inter.bn_num-1].bn_key; pinfo->newnode.bn_ptr.bn_ptr = pnewNode; return MOD_NOK; } int oldnum = pNode->bn_inter.bn_num; btk_t oldkey = pNode->bn_inter.bn_entry[oldnum-1].bn_key; bt_branch_real_add(&pNode->bn_inter, pinfo->newnode); pinfo->newnode.bn_ptr.bn_ptr = NULL; if(BT_LVL_ROOT != pNode->bn_level){ if(bt_key_cmp(oldkey, pNode->bn_inter.bn_entry[pNode->bn_inter.bn_num-1].bn_key) 0){ pinfo->midkey = 1; pinfo->newnode.bn_ptr.bn_ptr = NULL; pinfo->newnode.bn_key.bn_key = 0; return MOD_NOK; } } return MOD_OK; } void bt_branch_real_del(btinter_t * pbranch, int idx){ int i; btp_t tmpptr = {0}; tmpptr.bn_ptr = pbranch->bn_entry[idx].bn_ptr.bn_ptr; for(i=idx+1; ipbranch->bn_num; i++){ pbranch->bn_entry[i-1] = pbranch->bn_entry[i]; } pbranch->bn_num--; bt_free_node(tmpptr); } static inline void bt_branch_move2left(btinter_t * psrc, btinter_t * pdst, int move_num){ memcpy(pdst->bn_entry+pdst->bn_num, psrc->bn_entry, sizeof(bti_t)*move_num); pdst->bn_num += move_num; int i; for(i=0; i(psrc->bn_num - move_num); i++){ psrc->bn_entry[i] = psrc->bn_entry[i+move_num]; } psrc->bn_num -= move_num; } static inline void bt_branch_move2right(btinter_t * psrc, btinter_t * pdst, int move_num){ int idx = psrc->bn_num-move_num; int i; for(i=pdst->bn_num-1; i>=0; i--){ pdst->bn_entry[i+move_num] = pdst->bn_entry[i]; } memcpy(pdst->bn_entry, &psrc->bn_entry[idx], sizeof(bti_t)*move_num); pdst->bn_num += move_num; psrc->bn_num -= move_num; } static inline void bt_branch_rotate(btnode_t * plNode, btnode_t * pmNode, btnode_t * prNode, modinfo_t* pbrot, rot_t mode, int idx){ int i; int value = 0; int node_num = 0; btk_t oldkey[ORDNUM] = {0}; btinter_t * pleft = NULL; btinter_t * pmid = NULL; btinter_t * pright = NULL; btinter_t * target = NULL; if(NULL != plNode){ pleft = &plNode->bn_inter; value += pleft->bn_num; oldkey[LEFT] = pleft->bn_entry[pleft->bn_num-1].bn_key; node_num ++; } if(NULL != prNode){ pright = &prNode->bn_inter; value += pright->bn_num; oldkey[RIGHT] = pright->bn_entry[pright->bn_num-1].bn_key; node_num ++; } pmid = &pmNode->bn_inter; value += pmid->bn_num; oldkey[MID] = pmid->bn_entry[pmid->bn_num-1].bn_key; node_num++; int num[ORDNUM] = {0}; equal_divi(value, node_num, num); int move_num = 0; if(pleft != NULL && pright != NULL){ idx += pleft->bn_num; if(ROT_ADD == mode){ if(idx num[LEFT]){ target = pleft; if(num[LEFT] >= LEAF_KEY_NUM){ num[LEFT]--; if(num[MID] LEAF_KEY_NUM){ num[MID]++; } else{ num[RIGHT]++; } } } else if(idx num[LEFT]+num[MID]){ target = pmid; idx -= num[LEFT]; if(num[MID] >= LEAF_KEY_NUM){ num[MID]--; num[RIGHT]++; } } else{ target = pright; idx -= (num[LEFT] + num[MID]); } } } else if(NULL != pleft){ idx += pleft->bn_num; if(ROT_ADD == mode){ if(idx num[LEFT]-1){ target = pleft; if(num[LEFT] >= LEAF_KEY_NUM){ num[LEFT]--; num[MID]++; } } else{ idx -= num[LEFT]; target = pmid; } } } else if(NULL != pright){ num[RIGHT] = num[MID]; num[MID] = num[LEFT]; num[LEFT] = 0; if(ROT_ADD == mode){ if(idx num[MID]){ target = pmid; if(num[MID] >= LEAF_KEY_NUM){ num[MID]--; num[RIGHT]++; } } else{ idx -= num[MID]; target = pright; } } } if(NULL != pleft && NULL != pright){ if((num[LEFT] pleft->bn_num)&& (num[RIGHT] > pright->bn_num)){ move_num = num[RIGHT] - pright->bn_num; bt_branch_move2right(pmid, pright, move_num); move_num = pleft->bn_num - num[LEFT]; bt_branch_move2right(pleft, pmid, move_num); } else if((num[LEFT] > pleft->bn_num)&& (num[RIGHT] pright->bn_num)){ move_num = num[LEFT] - pleft->bn_num; bt_branch_move2left(pmid, pleft, move_num); move_num = pright->bn_num - num[RIGHT]; bt_branch_move2left(pright, pmid, move_num); } } if(NULL != pleft){ if(num[LEFT] pleft->bn_num){ move_num = pleft->bn_num - num[LEFT]; bt_branch_move2right(pleft, pmid, move_num); } else if(num[LEFT] > pleft->bn_num){ move_num = num[LEFT] - pleft->bn_num; bt_branch_move2left(pmid, pleft, move_num); } } if(NULL != pright){ if(num[RIGHT] > pright->bn_num){ move_num = num[RIGHT] - pright->bn_num; bt_branch_move2right(pmid, pright, move_num); } else if(num[RIGHT] pright->bn_num){ move_num = pright->bn_num - num[RIGHT]; bt_branch_move2left(pright, pmid, move_num); } } if(0 != bt_key_cmp(oldkey[MID],pmid->bn_entry[pmid->bn_num-1].bn_key)){ pbrot->midkey = 1; } if(NULL != pleft && 0 != bt_key_cmp(oldkey[LEFT], pleft->bn_entry[pleft->bn_num-1].bn_key)){ pbrot->leftkey = 1; } if(NULL != pright && 0 != bt_key_cmp(oldkey[RIGHT], pright->bn_entry[pright->bn_num-1].bn_key)){ pbrot->rightkey = 1; } } static inline void bt_branch_merge(btnode_t * pleft, btnode_t * pmid, btnode_t * pright, modinfo_t* pinfo){ int num = 0; int move_num = 0; if((pright == NULL) || (pleft != NULL && pleft != NULL && pleft->bn_inter.bn_num pright->bn_inter.bn_num)){ num = (pleft->bn_inter.bn_num + pmid->bn_inter.bn_num)/2; move_num = pleft->bn_inter.bn_num; bt_branch_move2right(&pleft->bn_inter, &pmid->bn_inter, move_num); pinfo->invalidnode = LEFT; } else if((pleft == NULL) ||(pleft != NULL && pleft != NULL && pleft->bn_inter.bn_num >= pright->bn_inter.bn_num)){ num = (pright->bn_inter.bn_num + pmid->bn_inter.bn_num)/2; move_num = pright->bn_inter.bn_num; bt_branch_move2left(&pright->bn_inter, &pmid->bn_inter,move_num); pinfo->invalidnode = RIGHT; } pinfo->midkey= 1; } modv_t bt_branch_del(btnode_t * pNode, int idx, modinfo_t * pinfo, ndflag_t flag){ modv_t ret; bt_branch_real_del(&pNode->bn_inter, idx); if(idx == pNode->bn_inter.bn_num){ switch(flag){ case LEFT: pinfo->leftkey = 1; break; case MID: pinfo->midkey = 1; break; case RIGHT: pinfo->rightkey = 1; break; default: break; } ret = MOD_NOK; } if(pNode->bn_inter.bn_num LEAF_KEY_NUM/2){ ret = MOD_NOK; } else{ pinfo->invalidnode = ORDNUM; } return ret; } static inline void bt_leaf_move2left(btleaf_t * psrc, btleaf_t * pdst, int move_num){ if(0 == move_num) return; memcpy(pdst->bn_data+pdst->bn_num, psrc->bn_data, sizeof(btk_t)*move_num); pdst->bn_num += move_num; int i; for(i=0; i(psrc->bn_num - move_num); i++){ psrc->bn_data[i] = psrc->bn_data[i+move_num]; } psrc->bn_num -= move_num; } static inline void bt_leaf_move2right(btleaf_t * psrc, btleaf_t * pdst, int move_num){ int i; for(i=pdst->bn_num-1; i>=0; i--){ pdst->bn_data[i+move_num] = pdst->bn_data[i]; } memcpy(pdst->bn_data, psrc->bn_data+psrc->bn_num-move_num, sizeof(btk_t)*move_num); pdst->bn_num += move_num; psrc->bn_num -= move_num; } int bt_leaf_split(btnode_t * pNode, btnode_t ** ppNewNode){ if(LEAF_KEY_NUM > pNode->bn_leaf.bn_num){ log_debug("The leaf no need split!\n"); return BTREE_FAIL; } btnode_t * ptmp = bt_new_node(pNode->bn_type); if(NULL == ptmp) return BTREE_FAIL; ptmp->bn_level = pNode->bn_level; ptmp->bn_leaf.lnode.next = pNode->bn_leaf.lnode.next; ptmp->bn_leaf.lnode.prev = &pNode->bn_leaf.lnode; if(NULL != pNode->bn_leaf.lnode.next){ pNode->bn_leaf.lnode.next->prev = &ptmp->bn_leaf.lnode; } pNode->bn_leaf.lnode.next = &ptmp->bn_leaf.lnode; bt_leaf_move2right(&pNode->bn_leaf, &ptmp->bn_leaf, LEAF_KEY_NUM/2); *ppNewNode = ptmp; return BTREE_OK; } static inline void bt_leaf_real_add(btleaf_t * pleaf, int idx, btk_t key){ btk_t * tmpkeys = pleaf->bn_data; if(0 == pleaf->bn_num){ tmpkeys[0] = key; } else if(idx >= pleaf->bn_num){ tmpkeys[idx] = key; } else if(bt_key_cmp(key, tmpkeys[idx]) 0){ int j; for(j=pleaf->bn_num; j>idx; j--){ tmpkeys[j] = tmpkeys[j-1]; } tmpkeys[idx] = key; } else{ tmpkeys[idx+1] = key; } pleaf->bn_num++; } static inline void bt_leaf_real_del(btleaf_t * pleaf, int idx){ int i; for(i=idx+1; ipleaf->bn_num; i++){ pleaf->bn_data[i-1] = pleaf->bn_data[i]; } pleaf->bn_num--; } static inline void bt_leaf_rotate(btnode_t * plNode, btnode_t * pmNode, btnode_t * prNode, modinfo_t * pinfo, rot_t mode, int idx, btk_t key){ int i; int value = 0; int node_num = 0; btk_t oldkey[ORDNUM] = {0}; btleaf_t * pleft = NULL; btleaf_t * pmid = NULL; btleaf_t * pright = NULL; btleaf_t * target = NULL; if(NULL != plNode){ pleft = &plNode->bn_leaf; value += pleft->bn_num; oldkey[LEFT] = pleft->bn_data[pleft->bn_num-1]; node_num ++; } if(NULL != prNode){ pright = &prNode->bn_leaf; value += pright->bn_num; oldkey[RIGHT] = pright->bn_data[pright->bn_num-1]; node_num ++; } pmid = &pmNode->bn_leaf; value += pmid->bn_num; oldkey[MID] = pmid->bn_data[pmid->bn_num-1]; node_num++; int num[ORDNUM] = {0}; equal_divi(value, node_num, num); int move_num = 0; if(pleft != NULL && pright != NULL){ idx += pleft->bn_num; if(ROT_ADD == mode){ if(idx num[LEFT]){ target = pleft; if(num[LEFT] >= LEAF_KEY_NUM){ num[LEFT]--; if(num[MID] LEAF_KEY_NUM){ num[MID]++; } else{ num[RIGHT]++; } } } else if(idx num[LEFT]+num[MID]){ target = pmid; idx -= num[LEFT]; if(num[MID] >= LEAF_KEY_NUM){ num[MID]--; num[RIGHT]++; } } else{ target = pright; idx -= (num[LEFT] + num[MID]); } } } else if(NULL != pleft){ idx += pleft->bn_num; if(ROT_ADD == mode){ if(idx num[LEFT]-1){ target = pleft; if(num[LEFT] >= LEAF_KEY_NUM){ num[LEFT]--; num[MID]++; } } else{ idx -= num[LEFT]; target = pmid; } } } else if(NULL != pright){ num[RIGHT] = num[MID]; num[MID] = num[LEFT]; num[LEFT] = 0; if(ROT_ADD == mode){ if(idx num[MID]){ target = pmid; if(num[MID] >= LEAF_KEY_NUM){ num[MID]--; num[RIGHT]++; } } else{ idx -= num[MID]; target = pright; } } } if(NULL != pleft && NULL != pright){ if((num[LEFT] pleft->bn_num)&& (num[RIGHT] > pright->bn_num)){ move_num = num[RIGHT] - pright->bn_num; bt_leaf_move2right(pmid, pright, move_num); move_num = pleft->bn_num - num[LEFT]; bt_leaf_move2right(pleft, pmid, move_num); } else if((num[LEFT] > pleft->bn_num)&& (num[RIGHT] pright->bn_num)){ move_num = num[LEFT] - pleft->bn_num; bt_leaf_move2left(pmid, pleft, move_num); move_num = pright->bn_num - num[RIGHT]; bt_leaf_move2left(pright, pmid, move_num); } } if(NULL != pleft){ / if(num[LEFT] pleft->bn_num){ move_num = pleft->bn_num - num[LEFT]; bt_leaf_move2right(pleft, pmid, move_num); } else if(num[LEFT] > pleft->bn_num){ move_num = num[LEFT] - pleft->bn_num; bt_leaf_move2left(pmid, pleft, move_num); } } if(NULL != pright){ if(num[RIGHT] > pright->bn_num){ move_num = num[RIGHT] - pright->bn_num; bt_leaf_move2right(pmid, pright, move_num); } else if(num[RIGHT] pright->bn_num){ move_num = pright->bn_num - num[RIGHT]; bt_leaf_move2left(pright, pmid, move_num); } } if(ROT_ADD == mode){ bt_leaf_real_add(target, idx, key); } if(0 != bt_key_cmp(oldkey[MID],pmid->bn_data[pmid->bn_num-1])){ pinfo->midkey = 1; log_debug("old mid key: %ld new mid key: %ld ", oldkey[MID].bn_key, pmid->bn_data[pmid->bn_num-1].bn_key); } if(NULL != pleft && 0 != bt_key_cmp(oldkey[LEFT], pleft->bn_data[pleft->bn_num-1])){ pinfo->leftkey = 1; log_debug("old left key: %ld new left key: %ld ", oldkey[LEFT].bn_key, pleft->bn_data[pleft->bn_num-1].bn_key); } if(NULL != pright && 0 != bt_key_cmp(oldkey[RIGHT], pright->bn_data[pright->bn_num-1])){ pinfo->rightkey = 1; log_debug("old right key: %ld new right key: %ld ", oldkey[RIGHT].bn_key, pright->bn_data[pright->bn_num-1].bn_key); } log_debug("\n"); } static inline void bt_leaf_merge(btnode_t * pNode0, btnode_t * pNode1, btnode_t * pNode2, modinfo_t * pinfo){ btleaf_t * pleft = NULL; if(NULL != pNode0) pleft = &pNode0->bn_leaf; btleaf_t * pmid = &pNode1->bn_leaf; btleaf_t * pright = NULL; if(NULL != pNode2) pright = &pNode2->bn_leaf; int move_num = 0; if(pright == NULL || (pright != NULL && pleft != NULL && pright->bn_num >= pleft->bn_num)){ if(NULL != pleft->lnode.prev){ pleft->lnode.prev->next = pleft->lnode.next; } if(NULL != pleft->lnode.next){ pleft->lnode.next->prev = pleft->lnode.prev; } move_num = pleft->bn_num; bt_leaf_move2right(pleft,pmid,move_num); pinfo->invalidnode = LEFT; } else if(pleft == NULL || ((pright != NULL && pleft!= NULL) && pleft->bn_num >= pright->bn_num)){ if(NULL != pright->lnode.prev){ pright->lnode.prev->next = pright->lnode.next; } if(NULL != pright->lnode.next){ pright->lnode.next->prev = pright->lnode.prev; } move_num = pright->bn_num; bt_leaf_move2left(pright,pmid, move_num); pinfo->midkey = 1; pinfo->invalidnode = RIGHT; } } modv_t bt_leaf_add(btpath_t path_node, btk_t key, modinfo_t * pinfo){ btnode_t * pleft = path_node.pleft; btnode_t * pright = path_node.pright; btnode_t * pmid = path_node.pmid; int total = pmid->bn_leaf.bn_num; int bc_num = 1; if(NULL != pleft){ total += pleft->bn_leaf.bn_num; bc_num++; } if(NULL != pright){ total += pright->bn_leaf.bn_num; bc_num++; } int idx = path_node.mididx; if(pmid->bn_leaf.bn_num == LEAF_KEY_NUM){ if(total == bc_num*LEAF_KEY_NUM){ btnode_t * pnewNode = NULL; if(BTREE_FAIL == bt_leaf_split(pmid, &pnewNode)){ return MOD_FAIL; } if(NULL == pnewNode){ return MOD_FAIL; } int ret = bt_key_cmp(key, pmid->bn_leaf.bn_data[pmid->bn_leaf.bn_num-1]); if(ret 0){ bt_leaf_real_add(&pmid->bn_leaf, idx, key); } else{ idx = bt_search_leaf(pnewNode, key); if(BTREE_FAIL == idx){ idx = pnewNode->bn_leaf.bn_num-1; } bt_leaf_real_add(&pnewNode->bn_leaf, idx, key); } pinfo->midkey = 1; pinfo->newnode.bn_key = pnewNode->bn_leaf.bn_data[pnewNode->bn_leaf.bn_num-1]; pinfo->newnode.bn_ptr.bn_ptr = pnewNode; return MOD_NOK; } else{ bt_leaf_rotate(pleft, pmid, pright, pinfo, ROT_ADD, idx, key); return MOD_NOK; } } btk_t oldkey = pmid->bn_leaf.bn_data[pmid->bn_leaf.bn_num-1]; bt_leaf_real_add(&pmid->bn_leaf, idx, key); if(BT_LVL_ROOT != pmid->bn_level){ if(bt_key_cmp(oldkey, pmid->bn_leaf.bn_data[pmid->bn_leaf.bn_num-1]) 0){ pinfo->midkey = 1; pinfo->leftkey = 0; pinfo->rightkey = 0; return MOD_NOK; } } return MOD_OK; } modv_t bt_leaf_del(btpath_t path, modinfo_t * pinfo){ modv_t ret; bt_leaf_real_del(&path.pmid->bn_leaf, path.mididx); if(path.mididx == path.pmid->bn_leaf.bn_num){ pinfo->midkey = 1; ret = MOD_NOK; } if(path.pmid->bn_leaf.bn_num LEAF_KEY_NUM/2){ pinfo->invalidnode = MID; ret = MOD_NOK; } return ret; } static inline int bt_branch_update(btnode_t * pNode, int idx){ if((0 > idx)||(pNode->bn_inter.bn_num idx)){ log_debug("Branch update abnormal, idx:%d elem number:%d", idx, pNode->bn_inter.bn_num); exit(0); } btnode_t * tmpSon = pNode->bn_inter.bn_entry[idx].bn_ptr.bn_ptr; if(TYPE_INT == tmpSon->bn_type){ pNode->bn_inter.bn_entry[idx].bn_key = tmpSon->bn_inter.bn_entry[tmpSon->bn_inter.bn_num-1].bn_key; } else{ pNode->bn_inter.bn_entry[idx].bn_key = tmpSon->bn_leaf.bn_data[tmpSon->bn_leaf.bn_num-1]; } if(idx == pNode->bn_inter.bn_num-1) return MOD_NOK; return MOD_OK; } modv_t bt_child_handle(btnode_t * pleft, btnode_t * pmid, btnode_t * pright, int idx, modinfo_t * pinfo){ int total = bt_keynum(pmid); int bc_num = 1; modv_t ret = MOD_OK; if(NULL != pleft){ total += bt_keynum(pleft); bc_num++; } if(NULL != pright){ total += bt_keynum(pright); bc_num++; } if(TYPE_LEAF == pmid->bn_type){ if(total >= bc_num*(LEAF_KEY_NUM/2)){ btk_t key; bt_leaf_rotate(pleft, pmid, pright, pinfo, ROT_DEL, idx, key); pinfo->invalidnode = ORDNUM; } else{ bt_leaf_merge(pleft, pmid, pright, pinfo); ret = MOD_NOK; } } else{ if(total >= bc_num * (INTER_KEY_NUM/2)){ btk_t key; bt_branch_rotate(pleft, pmid, pright, pinfo, ROT_DEL, idx); pinfo->invalidnode = ORDNUM; } else{ bt_branch_merge(pleft, pmid, pright, pinfo); ret = MOD_NOK; } } return ret; } void bt_getpath_bykey(btnode_t * proot, btk_t key, btpath_t * path, int level){ int i; if(NULL == proot){ return; } btnode_t * pleft = NULL; btnode_t * pmid = proot; btnode_t * pright = NULL; for(i=0; ilevel; i++){ path[i].pleft = pleft; path[i].pmid = pmid; path[i].pright = pright; if(pmid->bn_type == TYPE_INT){ path[i].mididx = bt_search_branch(pmid, key); if(path[i].mididx != BTREE_FAIL){ if(path[i].mididx > 0){ path[i].plfather = pmid; path[i].leftidx = path[i].mididx-1; pleft = pmid->bn_inter.bn_entry[path[i].mididx-1].bn_ptr.bn_ptr; } else if(NULL != pleft){ path[i].plfather = pleft; path[i].leftidx = pleft->bn_inter.bn_num-1; pleft = pleft->bn_inter.bn_entry[pleft->bn_inter.bn_num-1].bn_ptr.bn_ptr; } if(path[i].mididx pmid->bn_inter.bn_num-1){ path[i].prfather = pmid; path[i].rightidx = path[i].mididx+1; pright = pmid->bn_inter.bn_entry[path[i].mididx+1].bn_ptr.bn_ptr; } else if(NULL != pright){ path[i].prfather = pright; path[i].rightidx = 0; pright = pright->bn_inter.bn_entry[0].bn_ptr.bn_ptr; } pmid = pmid->bn_inter.bn_entry[path[i].mididx].bn_ptr.bn_ptr; } else{ path[i].mididx = pmid->bn_inter.bn_num-1; path[i].plfather = pmid; path[i].leftidx = path[i].mididx-1; pleft = pmid->bn_inter.bn_entry[path[i].leftidx].bn_ptr.bn_ptr; path[i].rightidx = 0; path[i].prfather = pright; if(NULL != pright){ pright = pright->bn_inter.bn_entry[0].bn_ptr.bn_ptr; } pmid = pmid->bn_inter.bn_entry[path[i].mididx].bn_ptr.bn_ptr; } } else if(pmid->bn_type == TYPE_LEAF){ path[i].mididx = bt_search_leaf(pmid, key); if(BTREE_FAIL != path[i].mididx){ if(path[i].mididx > 0){ path[i].plfather = pmid; path[i].leftidx = path[i].mididx-1; } else if(NULL != pleft){ path[i].plfather = pleft; path[i].leftidx = pleft->bn_leaf.bn_num-1; } if(path[i].mididx pmid->bn_leaf.bn_num-1){ path[i].prfather = pmid; path[i].rightidx = path[i].mididx+1; } else if(NULL != pright){ path[i].prfather = pright; path[i].rightidx = 0; } } else{ path[i].mididx = pmid->bn_leaf.bn_num-1; path[i].plfather = pmid; path[i].leftidx = path[i].mididx-1; path[i].rightidx = 0; path[i].prfather = pright; } } else{ log_debug("the tree is invalid, please check!\n"); exit(0); } log_debug("path[%d].idx:%d\n", i, path[i].mididx); } } int bt_branch_modify(btpath_t path, modinfo_t * pinfo){ int idx = 0; int isUpdate = 0; modv_t ret = MOD_OK; btnode_t * pleft = NULL; btnode_t * pmid = NULL; btnode_t * pright = NULL; if(0 != pinfo->midkey){ if(MOD_NOK == bt_branch_update(path.pmid, path.mididx)){ isUpdate = 1; } else{ pinfo->midkey = 0; } } if(0 != pinfo->leftkey){ bt_branch_update(path.plfather, path.leftidx); if(0 == path.mididx){ isUpdate = 1; } else{ pinfo->leftkey = 0; } } if(MID == pinfo->invalidnode){ if(NULL != path.plfather){ pleft = path.plfather->bn_inter.bn_entry[path.leftidx].bn_ptr.bn_ptr; } pmid = path.pmid->bn_inter.bn_entry[path.mididx].bn_ptr.bn_ptr; if(NULL != path.prfather){ pright = path.prfather->bn_inter.bn_entry[path.rightidx].bn_ptr.bn_ptr; } bt_child_handle(pleft, pmid, pright, idx, pinfo); if(0 != pinfo->leftkey){ if(MOD_NOK == bt_branch_update(path.plfather, path.leftidx)){ ret = MOD_NOK; } else{ pinfo->leftkey = 0; } } if(0 != pinfo->midkey){ if(MOD_NOK == bt_branch_update(path.pmid, path.mididx)){ ret = MOD_NOK; } else{ pinfo->midkey = 0; } } if(LEFT == pinfo->invalidnode){ ret = bt_branch_del(path.plfather, path.leftidx, pinfo, LEFT); } else if(RIGHT == pinfo->invalidnode){ ret = bt_branch_del(path.prfather, path.rightidx, pinfo, MID); } } else if(LEFT == pinfo->invalidnode){ btnode_t * plleft = NULL; int llidx = 0; if(path.leftidx == 0){ if(NULL != path.pleft){ pleft = path.pleft->bn_inter.bn_entry[path.pleft->bn_inter.bn_num-1].bn_ptr.bn_ptr; plleft = path.pleft; llidx = path.pleft->bn_inter.bn_num-1; } } else{ pleft = path.plfather->bn_inter.bn_entry[path.leftidx-1].bn_ptr.bn_ptr; plleft = path.plfather; llidx = path.leftidx-1; } if(NULL == path.plfather){ pmid = path.pmid->bn_inter.bn_entry[path.mididx].bn_ptr.bn_ptr; pright = path.prfather->bn_inter.bn_entry[path.rightidx].bn_ptr.bn_ptr; path.plfather = path.pmid; path.leftidx = path.mididx; } else{ pmid = path.plfather->bn_inter.bn_entry[path.leftidx].bn_ptr.bn_ptr; pright = path.pmid->bn_inter.bn_entry[path.mididx].bn_ptr.bn_ptr; path.prfather = path.pmid; path.rightidx= path.mididx; } bt_child_handle(pleft, pmid, pright, idx, pinfo); if(0 != pinfo->leftkey){ if(MOD_NOK == bt_branch_update(plleft, llidx)){ ret = MOD_NOK; } } if(0 != pinfo->midkey){ if(MOD_NOK == bt_branch_update(path.plfather, path.leftidx)){ ret = MOD_NOK; } } if(LEFT == pinfo->invalidnode){ ret = bt_branch_del(plleft, llidx, pinfo, LEFT); } else if(RIGHT == pinfo->invalidnode){ ret = bt_branch_del(path.prfather, path.rightidx, pinfo, MID); } } else if(RIGHT == pinfo->invalidnode){ pinfo->invalidnode = ORDNUM; pleft = path.pmid->bn_inter.bn_entry[path.mididx].bn_ptr.bn_ptr; pmid = path.prfather->bn_inter.bn_entry[path.rightidx].bn_ptr.bn_ptr; btnode_t * prright = NULL; int rridx = 0; if(path.rightidx == path.prfather->bn_inter.bn_num-1){ if(NULL != path.pright){ pright = path.pright->bn_inter.bn_entry[0].bn_ptr.bn_ptr; prright = path.pright; rridx = 0; } } else{ pright = path.prfather->bn_inter.bn_entry[path.rightidx+1].bn_ptr.bn_ptr; prright = path.prfather; rridx = path.rightidx+1; } bt_child_handle(pleft, pmid, pright, idx, pinfo); if(0 != pinfo->leftkey){ if(MOD_NOK == bt_branch_update(path.pmid, path.mididx)){ ret = MOD_NOK; } } if(0 != pinfo->midkey){ if(MOD_NOK == bt_branch_update(path.prfather, path.rightidx)){ ret = MOD_NOK; } } if(LEFT == pinfo->invalidnode){ ret = bt_branch_del(path.pmid, path.mididx, pinfo, MID); } else if(RIGHT == pinfo->invalidnode){ ret = bt_branch_del(prright, rridx, pinfo, RIGHT); } } if(NULL != pinfo->newnode.bn_ptr.bn_ptr){ ret = bt_branch_add(path.pmid, pinfo); } if((isUpdate == 1)&&(path.pmid->bn_level != BT_LVL_ROOT)){ return MOD_NOK; } return ret; } int bt_insert(bptree_t * ptree, btk_t key){ btpath_t path[BT_LVL_ROOT] = {0}; modinfo_t ist_info = {0}; ist_info.invalidnode = ORDNUM; modv_t ret = MOD_FAIL; int i = 0; bt_getpath_bykey(ptree->bpt_root, key, path, ptree->bpt_level); int cmp_ret = bt_key_cmp(path[ptree->bpt_level-1].pmid->bn_leaf.bn_data[path[ptree->bpt_level-1].mididx], key); if(0 == cmp_ret){ log_debug("The key you want insert is exist!\n"); return BTREE_OK; } else if(0 > cmp_ret){ path[ptree->bpt_level-1].mididx++; } for(i=ptree->bpt_level-1; i>=0; i--){ if(TYPE_LEAF == path[i].pmid->bn_type){ ret = bt_leaf_add(path[i], key, &ist_info); } else if(MOD_OK == ret){ break; } else if(MOD_FAIL == ret){ return BTREE_FAIL; } else{ ret = bt_branch_modify(path[i], &ist_info); } } if(MOD_NOK == ret){ btnode_t * newroot = bt_new_node(TYPE_INT); btnode_t * newbranch = (btnode_t *)ist_info.newnode.bn_ptr.bn_ptr; btnode_t * tmpNode = ptree->bpt_root; btp_t ptr; if(NULL == newroot){ log_debug("alloc new root for increase new level failed!\n"); return BTREE_FAIL; } newroot->bn_level = BT_LVL_ROOT; if(tmpNode->bn_type == TYPE_LEAF){ tmpNode->bn_level = BT_LVL_LEAF; newbranch->bn_level = BT_LVL_LEAF; } else{ tmpNode->bn_level = BT_LVL_INT; newbranch->bn_level = BT_LVL_INT; } newroot->bn_inter.bn_entry[0].bn_key = bt_maxkey(tmpNode); newroot->bn_inter.bn_entry[0].bn_ptr.bn_ptr = tmpNode; newroot->bn_inter.bn_entry[1] = ist_info.newnode; newroot->bn_inter.bn_num = 2; ptree->bpt_level++; ptree->bpt_root = newroot; } else if(MOD_FAIL == ret){ return BTREE_FAIL; } return BTREE_OK; } int bt_del(bptree_t * ptree, btk_t key){ btpath_t path[BT_LVL_ROOT] = {0}; modinfo_t del_info = {0}; del_info.invalidnode = ORDNUM; modv_t ret = MOD_FAIL; btnode_t * ptarget = NULL; int i; bt_getpath_bykey(ptree->bpt_root, key, path, ptree->bpt_level); int cmp_ret = bt_key_cmp(path[ptree->bpt_level-1].pmid->bn_leaf.bn_data[path[ptree->bpt_level-1].mididx], key); if(0 != cmp_ret){ log_debug("The key you want delete is not exist!\n"); return BTREE_OK; } for(i=ptree->bpt_level-1; i>=0; i--){ if(TYPE_LEAF == path[i].pmid->bn_type){ ret = bt_leaf_del(path[i], &del_info); } else if(MOD_OK == ret){ break; } else if(MOD_FAIL == ret){ return BTREE_FAIL; } else{ ret = bt_branch_modify(path[i], &del_info); } } if(MOD_NOK == ret){ ptarget = ptree->bpt_root; if(ptarget->bn_type != TYPE_LEAF){ if(ptarget->bn_inter.bn_num 1){ btnode_t * pNode = (btnode_t *)ptarget->bn_inter.bn_entry[0].bn_ptr.bn_ptr; pNode->bn_level = BT_LVL_ROOT; ptree->bpt_root = pNode; ptree->bpt_level --; del(ptarget); } } else{ log_debug("there are only %d entries!\n",ptarget->bn_leaf.bn_num); } } return BTREE_OK; } int bt_tree_check(bptree_t * ptree){ aque_t queue; btnode_t * pthis = NULL; btnode_t * prev = NULL; btnode_t * pson = NULL; int level = 0; btnode_t * pNode = ptree->bpt_root; while(1){ level++; if(pNode->bn_type == TYPE_INT){ pNode = (btnode_t *)pNode->bn_inter.bn_entry[0].bn_ptr.bn_ptr; } else{ break; } } if(level != ptree->bpt_level){ log_debug("level is wrong\n"); return BTREE_FAIL; } aque_init(&queue); aq_push(&queue,ptree->bpt_root); int i; while(queue.len>0){ pthis = aq_pop(&queue); if(TYPE_INT == pthis->bn_type){ if((INTER_KEY_NUM/2 > pthis->bn_inter.bn_num) && (BT_LVL_ROOT != pthis->bn_level)){ log_debug("the INT Node[%ld] not enough!\n", pthis->bn_inter.bn_entry[pthis->bn_inter.bn_num-1].bn_key.bn_key); return BTREE_FAIL; } for(i=0; ipthis->bn_inter.bn_num; i++){ if(NULL == pthis->bn_inter.bn_entry[i].bn_ptr.bn_ptr){ log_debug("the INT Node[%ld][%d] ptr is null!\n", pthis->bn_inter.bn_entry[i].bn_key.bn_key, i); return BTREE_FAIL; } else{ pson = pthis->bn_inter.bn_entry[i].bn_ptr.bn_ptr; } if(TYPE_INT == pson->bn_type){ if(bt_key_cmp(pthis->bn_inter.bn_entry[i].bn_key, pson->bn_inter.bn_entry[pson->bn_inter.bn_num-1].bn_key) != 0){ log_debug("The key[%ld] not equal son[INT] max key!\n", pthis->bn_inter.bn_entry[i].bn_key.bn_key); return BTREE_FAIL; } } else if(TYPE_LEAF == pson->bn_type){ if(bt_key_cmp(pthis->bn_inter.bn_entry[i].bn_key, pson->bn_leaf.bn_data[pson->bn_leaf.bn_num-1]) != 0){ log_debug("The key[%ld] not equal son[LEAF] max key!\n", pthis->bn_inter.bn_entry[i].bn_key.bn_key); return BTREE_FAIL; } } else{ log_debug("The Node[%ld]'s son node type[%d] is invalid!\n", pthis->bn_inter.bn_entry[i].bn_key.bn_key, pson->bn_type); return BTREE_FAIL; } if(i>0){ if(bt_key_cmp(pthis->bn_inter.bn_entry[i-1].bn_key, pthis->bn_inter.bn_entry[i].bn_key) >= 0){ log_debug("the INT Node[%ld][%d] key is not sorted!\n", pthis->bn_inter.bn_entry[i].bn_key.bn_key, i); return BTREE_FAIL; } } aq_push(&queue, pson); } if(NULL != prev){ if(TYPE_INT == prev->bn_type){ if(bt_key_cmp(prev->bn_inter.bn_entry[prev->bn_inter.bn_num-1].bn_key, pthis->bn_inter.bn_entry[0].bn_key) >= 0){ if(prev->bn_level == pthis->bn_level){ log_debug("prev node max key bigger than this node first key\n"); return BTREE_FAIL; } } } else{ log_debug("INT node's prev node is not INT\n"); return BTREE_FAIL; } } } else if(TYPE_LEAF == pthis->bn_type){ if((LEAF_KEY_NUM/2 > pthis->bn_leaf.bn_num) && (BT_LVL_ROOT != pthis->bn_level)){ log_debug("the LEAF Node[%ld] not enough!\n", pthis->bn_leaf.bn_data[i].bn_key); return BTREE_FAIL; } for(i=0; ipthis->bn_leaf.bn_num; i++){ if(i>0){ if(bt_key_cmp(pthis->bn_leaf.bn_data[i-1], pthis->bn_leaf.bn_data[i]) >= 0){ log_debug("the LEAF Node[%ld][%d] key is not sorted!\n", pthis->bn_leaf.bn_data[i].bn_key, i); return BTREE_FAIL; } } } if(NULL != prev){ if(TYPE_INT == prev->bn_type){ if(bt_key_cmp(prev->bn_inter.bn_entry[prev->bn_inter.bn_num-1].bn_key, pthis->bn_leaf.bn_data[0]) 0){ log_debug("last level node max key[%ld] smaller than this node first key[%ld]\n", prev->bn_inter.bn_entry[prev->bn_inter.bn_num-1].bn_key.bn_key, pthis->bn_leaf.bn_data[0].bn_key); return BTREE_FAIL; } } else if(TYPE_LEAF== prev->bn_type){ if(bt_key_cmp(prev->bn_leaf.bn_data[prev->bn_leaf.bn_num-1], pthis->bn_leaf.bn_data[0]) >= 0){ log_debug("prev node max key bigger than this node first key\n"); return BTREE_FAIL; } } else { log_debug("LEAF node's prev node is invalid\n"); return BTREE_FAIL; } } } else{ log_debug("Node type is wrong!\n"); return BTREE_FAIL; } prev = pthis; } return BTREE_OK; } void bt_init(bptree_t * ptree){ ptree->bpt_leaf_nums = LEAF_KEY_NUM; ptree->bpt_branch_nums = INTER_KEY_NUM; ptree->bpt_level = 1; ptree->bpt_root = NULL; } void bt_create_root(bptree_t * ptree){ ptree->bpt_root = bt_new_node(TYPE_LEAF); ptree->bpt_root->bn_level = BT_LVL_ROOT; ptree->bpt_root->bn_type = TYPE_LEAF; ptree->bpt_root->bn_leaf.bn_num = 0; } #if 1 int get_tree_leaf_num(btnode_t * proot){ btleaf_t * pleaf = NULL; btnode_t * pNode = proot; while(pNode->bn_type != TYPE_LEAF){ pNode = (btnode_t *)pNode->bn_inter.bn_entry[0].bn_ptr.bn_ptr; } pleaf = &pNode->bn_leaf; struct list_head * plnode = &pleaf->lnode; int num = pleaf->bn_num; while(plnode->next != NULL){ plnode = plnode->next; pleaf = (btleaf_t *)plnode; num += pleaf->bn_num; } return num; } void print_btree_info(bptree_t * ptree){ log_debug("B+ Tree level num:%d\n", ptree->bpt_level); log_debug("B+ Tree branch node key num:%d\n", ptree->bpt_branch_nums); log_debug("B+ Tree leaf node key num:%d\n", ptree->bpt_leaf_nums); log_debug("B+ Tree have %d datas\n", get_tree_leaf_num(ptree->bpt_root)); } void print_leaf(btleaf_t * pleaf, char * prefix){ if(pleaf->bn_num 0){ log_debug("There is no data, please insert!\n"); return; } int i = 0; for(i=0; ipleaf->bn_num-1; i++){ printf("%s├────%ld\r\n",prefix, pleaf->bn_data[i].bn_key); } printf("%s└────%ld\r\n",prefix, pleaf->bn_data[i].bn_key); } void print_btree(bptree_t * ptree) { if((NULL == ptree) || (NULL != ptree && NULL == ptree->bpt_root)){ return; } btpath_t path[BT_LVL_ROOT] = {0}; int cusor = 0; path[cusor].pmid = ptree->bpt_root; path[cusor].mididx= 0; cusor++; btnode_t * tmpNode = NULL; btp_t ptr; char prefix[100] = {0}; int pre_idx = 0; printf("Root\n"); while(cusor){ tmpNode = path[cusor-1].pmid; if(TYPE_LEAF != tmpNode->bn_type){ if(path[cusor-1].mididx tmpNode->bn_inter.bn_num){ if(path[cusor-1].mididx == tmpNode->bn_inter.bn_num-1){ printf("%s└────%ld\n", prefix, tmpNode->bn_inter.bn_entry[path[cusor-1].mididx].bn_key.bn_key); sprintf(prefix, "%s ", prefix); } else{ printf("%s├────%ld\n", prefix, tmpNode->bn_inter.bn_entry[path[cusor-1].mididx].bn_key.bn_key); sprintf(prefix, "%s│ ", prefix); } path[cusor].pmid = (btnode_t *)tmpNode->bn_inter.bn_entry[path[cusor-1].mididx].bn_ptr.bn_ptr; path[cusor-1].mididx ++; path[cusor].mididx = 0; cusor ++; pre_idx += 8; prefix[pre_idx] = 0; } else{ cusor--; pre_idx -= 8; prefix[pre_idx] = 0; } } else{ print_leaf(&tmpNode->bn_leaf, prefix); cusor --; pre_idx -= 8; prefix[pre_idx] = 0; } } } #endif void write_node(btnode_t * pNode, int fd, int num){ if(NULL == pNode) return; char buf[1024] = {0}; int i = 0; if(pNode->bn_type == TYPE_INT){ sprintf(buf, "\n%d ### INT %d :", num, pNode->bn_level); for(i=0; ipNode->bn_inter.bn_num; i++){ sprintf(buf, "%s - [ %ld : %ld ]", buf, (unsigned long)(pNode->bn_inter.bn_entry[i].bn_ptr.bn_ptr), pNode->bn_inter.bn_entry[i].bn_key.bn_key); } } else{ sprintf(buf, "\n%d ### LEAF %d :", num, pNode->bn_level); for(i=0; ipNode->bn_leaf.bn_num; i++){ sprintf(buf, "%s - %ld", buf, pNode->bn_leaf.bn_data[i].bn_key); } } printf("%s\n", buf); write(fd, buf, strlen(buf)); } void dump_tree(bptree_t * ptree, int fd){ if((NULL == ptree) || (NULL != ptree && NULL == ptree->bpt_root)){ return; } btnode_t * pNode = NULL; char buf[NODE_SIZE]; btnode_t * tmpNode = (btnode_t *)buf; aque_t queue; unsigned long long offset = 0; int num = 0; sprintf(buf, "\nData count:%d", get_tree_leaf_num(ptree->bpt_root)); write(fd, buf, strlen(buf)); aque_init(&queue); aq_push(&queue, ptree->bpt_root); while(queue.len > 0){ pNode = aq_pop(&queue); if(pNode->bn_type == TYPE_INT){ memcpy(buf, pNode, NODE_SIZE); int i; for(i=0; ipNode->bn_inter.bn_num; i++){ offset += 1; aq_push(&queue, pNode->bn_inter.bn_entry[i].bn_ptr.bn_ptr); tmpNode->bn_inter.bn_entry[i].bn_ptr.bn_ptr = (void *)offset; } pNode = tmpNode; } write_node(pNode, fd, num++); } } void load_tree(bptree_t * ptree, char * tree_name){ char * keystr = NULL; char * remainstr = NULL; char line[200] = {0}; char typestr[5] = {0}; btype_t type; int key = 0; int ptr = 0; int level = 0; btnode_t * pNode = NULL; btnode_t * prev = NULL; bti_t * tmp = NULL; long file_seek = 0; int number = 0; if(ptree->bpt_root != NULL){ return; } FILE * pfile = fopen(tree_name, "r"); if(NULL == pfile){ return; } aque_t queue; aque_init(&queue); do{ if(NULL == fgets(line, 199, pfile)){ log_debug("tree file is end!\n"); break; } sscanf(line, "%d ### %s %d : %*s", &number, typestr, &level); if(strcmp(typestr, "INT") == 0){ type = TYPE_INT; } else if(strcmp(typestr, "LEAF") == 0){ type = TYPE_LEAF; } else{ log_debug("[LOAD]type error\n"); return; } pNode = bt_new_node(type); if(BT_LVL_ROOT == level){ ptree->bpt_root = pNode; } if(TYPE_LEAF == type){ if(NULL == prev){ pre***ode; } else{ prev->bn_leaf.lnode.next = &pNode->bn_leaf.lnode; pNode->bn_leaf.lnode.prev = &prev->bn_leaf.lnode; pre***ode; } } pNode->bn_level = level; tmp = aq_pop(&queue); if(NULL != tmp){ tmp->bn_ptr.bn_ptr = (void *)pNode; } keystr = strchr(line, '-'); int i = 0; while(keystr){ if(TYPE_INT == type){ sscanf(keystr, "- [%d : %d] -%*s", &ptr, &key); pNode->bn_inter.bn_entry[i].bn_key.bn_key = key; pNode->bn_inter.bn_entry[i].bn_ptr.bn_ptr = (void *)ptr; aq_push(&queue, &pNode->bn_inter.bn_entry[i]); pNode->bn_inter.bn_num++; } else{ sscanf(keystr, "- %d -%*s", &key); pNode->bn_leaf.bn_data[i].bn_key = key; pNode->bn_leaf.bn_num++; } keystr += 1; keystr = strchr(keystr, '-'); i++; } } while(queue.len>0); pNode = ptree->bpt_root; level = 0; while(1){ level++; if(pNode->bn_type == TYPE_INT){ pNode = (btnode_t *)pNode->bn_inter.bn_entry[0].bn_ptr.bn_ptr; } else{ break; } } ptree->bpt_level = level; } void save_tree_data(bptree_t * ptree, int fd){ char buf[12]; btleaf_t * pleaf = NULL; btnode_t * pNode = ptree->bpt_root; while(pNode->bn_type != TYPE_LEAF){ pNode = (btnode_t *)pNode->bn_inter.bn_entry[0].bn_ptr.bn_ptr; } pleaf = &pNode->bn_leaf; while(pleaf != NULL){ int i; memset(buf, 0, 12); for(i=0; ipleaf->bn_num; i++){ snprintf(buf, 12, "%ld\n", pleaf->bn_data[i].bn_key); write(fd, buf, strlen(buf)); } pleaf = (btleaf_t *)pleaf->lnode.next; } } void print_prompt() { log_debug("Insert node please press 'i'!\n"); log_debug("Delete node please press 'd'!\n"); log_debug("Print tree please press 'p'!\n"); log_debug("Get prompt please press '?'!\n"); log_debug("Quit this program please press 'q'!\n"); } void print_eof() { log_debug("#input order[insert/del/print/?/quit]:"); }
全部评论
(1) 回帖