B+tree详解及实现(C语言)
来源:互联网 发布:php api接口开发 编辑:程序博客网 时间:2024/06/09 14:01
1 什么是B+tree
如果你还不了解B-tree,那么请自行了解。可以参考我的这篇帖子---B-tree详解及实现。
B+tree是B-tree的一个变种:在B-tree的基础上,为叶子节点增加链表指针,而且所有的关键字都在叶子节点中出现,且数据只存储在叶子节点中。非叶子节点的关键字仅作为叶子节点的索引。下图是一棵B+tree。
B+tree 的插入和删除基本和B-tree一样,只是多了数据结构多了next字段,所以要注意。
2. B+tree的实现
2.1 头文件
//// BPlusTree.h// BPlusTree//// Created by Wuyixin on 2017/8/4.// Copyright © 2017年 Coding365. All rights reserved.//#ifndef BPlusTree_h#define BPlusTree_h#include <stdio.h>#include <stdlib.h>#include <limits.h>#define M (4)#define LIMIT_M_2 (M % 2 ? (M + 1)/2 : M/2)typedef struct BPlusNode *BPlusTree,*Position;typedef int KeyType;struct BPlusNode{ int KeyNum; KeyType Key[M + 1]; BPlusTree Children[M + 1]; BPlusTree Next;};/* 初始化 */extern BPlusTree Initialize();/* 插入 */extern BPlusTree Insert(BPlusTree T,KeyType Key);/* 删除 */extern BPlusTree Remove(BPlusTree T,KeyType Key);/* 销毁 */extern BPlusTree Destroy(BPlusTree T);/* 遍历节点 */extern void Travel(BPlusTree T);/* 遍历树叶节点的数据 */extern void TravelData(BPlusTree T);#endif /* BPlusTree_h */
2.2 实现文件
//// BPlusTree.c// BPlusTree//// Created by Wuyixin on 2017/8/4.// Copyright © 2017年 Coding365. All rights reserved.//#include "BPlusTree.h"static KeyType Unavailable = INT_MIN;/* 生成节点并初始化 */static BPlusTree MallocNewNode(){ BPlusTree NewNode; int i; NewNode = malloc(sizeof(struct BPlusNode)); if (NewNode == NULL) exit(EXIT_FAILURE); i = 0; while (i < M + 1){ NewNode->Key[i] = Unavailable; NewNode->Children[i] = NULL; i++; } NewNode->Next = NULL; NewNode->KeyNum = 0; return NewNode;}/* 初始化 */extern BPlusTree Initialize(){ BPlusTree T; if (M < (3)){ printf("M最小等于3!"); exit(EXIT_FAILURE); } /* 根结点 */ T = MallocNewNode(); return T;}static Position FindMostLeft(Position P){ Position Tmp; Tmp = P; while (Tmp != NULL && Tmp->Children[0] != NULL) { Tmp = Tmp->Children[0]; } return Tmp;}static Position FindMostRight(Position P){ Position Tmp; Tmp = P; while (Tmp != NULL && Tmp->Children[Tmp->KeyNum - 1] != NULL) { Tmp = Tmp->Children[Tmp->KeyNum - 1]; } return Tmp;}/* 寻找一个兄弟节点,其存储的关键字未满,否则返回NULL */static Position FindSibling(Position Parent,int i){ Position Sibling; int Limit; Limit = M; Sibling = NULL; if (i == 0){ if (Parent->Children[1]->KeyNum < Limit) Sibling = Parent->Children[1]; } else if (Parent->Children[i - 1]->KeyNum < Limit) Sibling = Parent->Children[i - 1]; else if (i + 1 < Parent->KeyNum && Parent->Children[i + 1]->KeyNum < Limit){ Sibling = Parent->Children[i + 1]; } return Sibling;}/* 查找兄弟节点,其关键字数大于M/2 ;没有返回NULL*/static Position FindSiblingKeyNum_M_2(Position Parent,int i,int *j){ int Limit; Position Sibling; Sibling = NULL; Limit = LIMIT_M_2; if (i == 0){ if (Parent->Children[1]->KeyNum > Limit){ Sibling = Parent->Children[1]; *j = 1; } } else{ if (Parent->Children[i - 1]->KeyNum > Limit){ Sibling = Parent->Children[i - 1]; *j = i - 1; } else if (i + 1 < Parent->KeyNum && Parent->Children[i + 1]->KeyNum > Limit){ Sibling = Parent->Children[i + 1]; *j = i + 1; } } return Sibling;}/* 当要对X插入Key的时候,i是X在Parent的位置,j是Key要插入的位置 当要对Parent插入X节点的时候,i是要插入的位置,Key和j的值没有用 */static Position InsertElement(int isKey, Position Parent,Position X,KeyType Key,int i,int j){ int k; if (isKey){ /* 插入key */ k = X->KeyNum - 1; while (k >= j){ X->Key[k + 1] = X->Key[k];k--; } X->Key[j] = Key; if (Parent != NULL) Parent->Key[i] = X->Key[0]; X->KeyNum++; }else{ /* 插入节点 */ /* 对树叶节点进行连接 */ if (X->Children[0] == NULL){ if (i > 0) Parent->Children[i - 1]->Next = X; X->Next = Parent->Children[i]; } k = Parent->KeyNum - 1; while (k >= i){ Parent->Children[k + 1] = Parent->Children[k]; Parent->Key[k + 1] = Parent->Key[k]; k--; } Parent->Key[i] = X->Key[0]; Parent->Children[i] = X; Parent->KeyNum++; } return X;}static Position RemoveElement(int isKey, Position Parent,Position X,int i,int j){ int k,Limit; if (isKey){ Limit = X->KeyNum; /* 删除key */ k = j + 1; while (k < Limit){ X->Key[k - 1] = X->Key[k];k++; } X->Key[X->KeyNum - 1] = Unavailable; Parent->Key[i] = X->Key[0]; X->KeyNum--; }else{ /* 删除节点 */ /* 修改树叶节点的链接 */ if (X->Children[0] == NULL && i > 0){ Parent->Children[i - 1]->Next = Parent->Children[i + 1]; } Limit = Parent->KeyNum; k = i + 1; while (k < Limit){ Parent->Children[k - 1] = Parent->Children[k]; Parent->Key[k - 1] = Parent->Key[k]; k++; } Parent->Children[Parent->KeyNum - 1] = NULL; Parent->Key[Parent->KeyNum - 1] = Unavailable; Parent->KeyNum--; } return X;}/* Src和Dst是两个相邻的节点,i是Src在Parent中的位置; 将Src的元素移动到Dst中 ,n是移动元素的个数*/static Position MoveElement(Position Src,Position Dst,Position Parent,int i,int n){ KeyType TmpKey; Position Child; int j,SrcInFront; SrcInFront = 0; if (Src->Key[0] < Dst->Key[0]) SrcInFront = 1; j = 0; /* 节点Src在Dst前面 */ if (SrcInFront){ if (Src->Children[0] != NULL){ while (j < n) { Child = Src->Children[Src->KeyNum - 1]; RemoveElement(0, Src, Child, Src->KeyNum - 1, Unavailable); InsertElement(0, Dst, Child, Unavailable, 0, Unavailable); j++; } }else{ while (j < n) { TmpKey = Src->Key[Src->KeyNum -1]; RemoveElement(1, Parent, Src, i, Src->KeyNum - 1); InsertElement(1, Parent, Dst, TmpKey, i + 1, 0); j++; } } Parent->Key[i + 1] = Dst->Key[0]; /* 将树叶节点重新连接 */ if (Src->KeyNum > 0) FindMostRight(Src)->Next = FindMostLeft(Dst); }else{ if (Src->Children[0] != NULL){ while (j < n) { Child = Src->Children[0]; RemoveElement(0, Src, Child, 0, Unavailable); InsertElement(0, Dst, Child, Unavailable, Dst->KeyNum, Unavailable); j++; } }else{ while (j < n) { TmpKey = Src->Key[0]; RemoveElement(1, Parent, Src, i, 0); InsertElement(1, Parent, Dst, TmpKey, i - 1, Dst->KeyNum); j++; } } Parent->Key[i] = Src->Key[0]; if (Src->KeyNum > 0) FindMostRight(Dst)->Next = FindMostLeft(Src); } return Parent;}static BPlusTree SplitNode(Position Parent,Position X,int i){ int j,k,Limit; Position NewNode; NewNode = MallocNewNode(); k = 0; j = X->KeyNum / 2; Limit = X->KeyNum; while (j < Limit){ if (X->Children[0] != NULL){ NewNode->Children[k] = X->Children[j]; X->Children[j] = NULL; } NewNode->Key[k] = X->Key[j]; X->Key[j] = Unavailable; NewNode->KeyNum++;X->KeyNum--; j++;k++; } if (Parent != NULL) InsertElement(0, Parent, NewNode, Unavailable, i + 1, Unavailable); else{ /* 如果是X是根,那么创建新的根并返回 */ Parent = MallocNewNode(); InsertElement(0, Parent, X, Unavailable, 0, Unavailable); InsertElement(0, Parent, NewNode, Unavailable, 1, Unavailable); return Parent; } return X;}/* 合并节点,X少于M/2关键字,S有大于或等于M/2个关键字*/static Position MergeNode(Position Parent, Position X,Position S,int i){ int Limit; /* S的关键字数目大于M/2 */ if (S->KeyNum > LIMIT_M_2){ /* 从S中移动一个元素到X中 */ MoveElement(S, X, Parent, i,1); }else{ /* 将X全部元素移动到S中,并把X删除 */ Limit = X->KeyNum; MoveElement(X,S, Parent, i,Limit); RemoveElement(0, Parent, X, i, Unavailable); free(X); X = NULL; } return Parent;}static BPlusTree RecursiveInsert(BPlusTree T,KeyType Key,int i,BPlusTree Parent){ int j,Limit; Position Sibling; /* 查找分支 */ j = 0; while (j < T->KeyNum && Key >= T->Key[j]){ /* 重复值不插入 */ if (Key == T->Key[j]) return T; j++; } if (j != 0 && T->Children[0] != NULL) j--; /* 树叶 */ if (T->Children[0] == NULL) T = InsertElement(1, Parent, T, Key, i, j); /* 内部节点 */ else T->Children[j] = RecursiveInsert(T->Children[j], Key, j, T); /* 调整节点 */ Limit = M; if (T->KeyNum > Limit){ /* 根 */ if (Parent == NULL){ /* 分裂节点 */ T = SplitNode(Parent, T, i); } else{ Sibling = FindSibling(Parent, i); if (Sibling != NULL){ /* 将T的一个元素(Key或者Child)移动的Sibing中 */ MoveElement(T, Sibling, Parent, i, 1); }else{ /* 分裂节点 */ T = SplitNode(Parent, T, i); } } } if (Parent != NULL) Parent->Key[i] = T->Key[0]; return T;}/* 插入 */extern BPlusTree Insert(BPlusTree T,KeyType Key){ return RecursiveInsert(T, Key, 0, NULL);}static BPlusTree RecursiveRemove(BPlusTree T,KeyType Key,int i,BPlusTree Parent){ int j,NeedAdjust; Position Sibling,Tmp; Sibling = NULL; /* 查找分支 */ j = 0; while (j < T->KeyNum && Key >= T->Key[j]){ if (Key == T->Key[j]) break; j++; } if (T->Children[0] == NULL){ /* 没找到 */ if (Key != T->Key[j] || j == T->KeyNum) return T; }else if (j == T->KeyNum || Key < T->Key[j]) j--; /* 树叶 */ if (T->Children[0] == NULL){ T = RemoveElement(1, Parent, T, i, j); }else{ T->Children[j] = RecursiveRemove(T->Children[j], Key, j, T); } NeedAdjust = 0; /* 树的根或者是一片树叶,或者其儿子数在2到M之间 */ if (Parent == NULL && T->Children[0] != NULL && T->KeyNum < 2) NeedAdjust = 1; /* 除根外,所有非树叶节点的儿子数在[M/2]到M之间。(符号[]表示向上取整) */ else if (Parent != NULL && T->Children[0] != NULL && T->KeyNum < LIMIT_M_2) NeedAdjust = 1; /* (非根)树叶中关键字的个数也在[M/2]和M之间 */ else if (Parent != NULL && T->Children[0] == NULL && T->KeyNum < LIMIT_M_2) NeedAdjust = 1; /* 调整节点 */ if (NeedAdjust){ /* 根 */ if (Parent == NULL){ if(T->Children[0] != NULL && T->KeyNum < 2){ Tmp = T; T = T->Children[0]; free(Tmp); return T; } }else{ /* 查找兄弟节点,其关键字数目大于M/2 */ Sibling = FindSiblingKeyNum_M_2(Parent, i,&j); if (Sibling != NULL){ MoveElement(Sibling, T, Parent, j, 1); }else{ if (i == 0) Sibling = Parent->Children[1]; else Sibling = Parent->Children[i - 1]; Parent = MergeNode(Parent, T, Sibling, i); T = Parent->Children[i]; } } } return T;}/* 删除 */extern BPlusTree Remove(BPlusTree T,KeyType Key){ return RecursiveRemove(T, Key, 0, NULL);}/* 销毁 */extern BPlusTree Destroy(BPlusTree T){ int i,j; if (T != NULL){ i = 0; while (i < T->KeyNum + 1){ Destroy(T->Children[i]);i++; } printf("Destroy:("); j = 0; while (j < T->KeyNum)/* T->Key[i] != Unavailable*/ printf("%d:",T->Key[j++]); printf(") "); free(T); T = NULL; } return T;}static void RecursiveTravel(BPlusTree T,int Level){ int i; if (T != NULL){ printf(" "); printf("[Level:%d]-->",Level); printf("("); i = 0; while (i < T->KeyNum)/* T->Key[i] != Unavailable*/ printf("%d:",T->Key[i++]); printf(")"); Level++; i = 0; while (i <= T->KeyNum) { RecursiveTravel(T->Children[i], Level); i++; } }}/* 遍历 */extern void Travel(BPlusTree T){ RecursiveTravel(T, 0); printf("\n");}/* 遍历树叶节点的数据 */extern void TravelData(BPlusTree T){ Position Tmp; int i; if (T == NULL) return ; printf("All Data:"); Tmp = T; while (Tmp->Children[0] != NULL) Tmp = Tmp->Children[0]; /* 第一片树叶 */ while (Tmp != NULL){ i = 0; while (i < Tmp->KeyNum) printf(" %d",Tmp->Key[i++]); Tmp = Tmp->Next; }}
2.3 调用
//// main.c// BPlusTree//// Created by Wuyixin on 2017/8/4.// Copyright © 2017年 Coding365. All rights reserved.//#include <stdio.h>#include <time.h>#include "BPlusTree.h"int main(int argc, const char * argv[]) { int i; BPlusTree T; T = Initialize(); clock_t c1 = clock(); i = 10000000; while (i > 0) T = Insert(T, i--); i = 5000001; while (i < 10000000) T = Insert(T, i++); i = 10000000; while (i > 100) T = Remove(T, i--); Travel(T); Destroy(T); clock_t c2 = clock(); printf("\n用时: %lu秒\n",(c2 - c1)/CLOCKS_PER_SEC);}
阅读全文
1 0
- B-tree详解及实现(C语言)
- B+tree详解及实现(C语言)
- RSA算法详解及C语言实现
- RSA算法详解及C语言实现
- RSA算法详解及C语言实现
- RSA算法详解及C语言实现
- RSA算法详解及C语言实现
- RSA算法详解及C语言实现
- 伸展树详解及实现(C语言)
- c语言实现tree数据结构
- AVL Tree C语言实现
- C语言实现tree命令
- B树C语言实现
- B+树C语言实现
- B_TREE B+TREE(C 实现)
- [转]BM算法详解及C语言实现
- 九大排序算法-C语言实现及详解
- 九大排序算法-c语言实现及详解
- tensorflow mnist入门
- 十个必会Jquery应用
- CSU-ACM2017暑期训练14-最短路 D
- 使用fastjson的parseObject方法将json字符串转换成Map 或者List
- 【HDU2089】不要62 数位DP
- B+tree详解及实现(C语言)
- Mysql入门与基础命令
- PHP魔术方法
- Unity_Unet基础使用一
- Windows 服务器 部署JAVA Web
- JAVA中this三种方法详解
- Javascript 基础(一)
- MySQL与MongoDB语法对比(简单)
- 安卓插件化实例