B+ 树的概念
- B+ 树可以看作是B- 树的一种变形,再实现文件索引结构方面比B- 树使用得更普遍
- 一颗 m 阶 B+ 树可以定义如下:
- 树中每个非叶结点最多有m棵子树
- 根节点(非叶结点)至少有 2 颗子树,除了根结点外,其它的非叶结点至少有[m/2]棵子树,有 n 棵子树的非叶结点有 n-1 个关键码
- 所有的叶节点都处于同一层次上,包含了全部关键码及指向相应数据对象存放地址的指针,且叶结点本身按关键码从小到大顺序链接
- 每个叶结点中的子树棵树 n 可以多于 m ,可以少于 m ,视关键码字节数及对象地址指针字节数而定;若设结点可容纳最大关键码数为 m1 ,则指向对象的地址指针也有 m1 个;结点中的子树棵树 n 应满足 n [[m1/2],m1]
- 若根节点同时又是叶结点,则结点格式同叶结点
- 所有的非叶结点可以看成是索引部分,结点中关键码 Ki 与指向子树的指针pi构成对子树(即下一层索引块)的索引项(Ki,Pi),Ki是子树中最小的关键码,特别地,子树指针P0所指子树上所有关键码,特别地,子树指针P0所指子树上所有关键码均小于K1,结点格式同B-树
B+ 树与 B- 树的叶子结构不同,B+树中所有的关键码均再叶子结点,也就是要不断查询直至到达叶子结点,而B-树中关键码不但存在于叶子结点也存在于分支结点
B+ 树的定义
#define M 5
#define BRCHMAX (M-1) //分支中最大元素个数
#define BRCHMIN (M/2) //最小
#define LEAFMAX (M-1) //MAX ELEM 5
#define LEAFMIN (M/2+1)//MIN ELEM 3
typedef char KeyType;
typedef struct {}Record;
typedef enum { BRCH = 1, LEAF = 2 }NodeType;
typedef struct BNode
{
int num; //elem size 元素个数
BNode* parent;
NodeType utype; //LEAF BRCH
KeyType key[M + 1];
union
{
//LEAF 叶节点
struct
{
Record* recpte[M + 1]; //记录集
BNode* prev, * next;
};
//BRCH 分支
BNode* sub[M + 1];
};
};
typedef struct
{
struct BNode* root;
struct BNode* first;
int cursize;
}BTree;
typedef struct
{
struct BNode* pnode;
int index;
bool tag; //返回false 则 需要在index位置插入
}Result; //返回结构
B+ 树的插入
#define M 5 // M 奇数 //
#define BRCHMAX (M-1) // // SUB M
#define BRCHMIN (M/2); // SUB M/2+1
#define LEAFMAX (M) // MAX ELEM 5
#define LEAFMIN (M/2+1) // MIN ELEM; 3
typedef int KeyType;
typedef struct {}Record;
typedef enum { BRCH = 1, LEAF = 2 } NodeType;
typedef struct BNode
{
int num; // elem size; // LEFT BRCH
BNode* parent;
NodeType utype; // LEAF , BRCH;
KeyType key[M + 1];
union
{
struct // LEAF
{
Record* recptr[M + 1];
BNode* prev, * next;
};
// BRCH;
BNode* sub[M + 1];
};
}BNode;
typedef struct
{
struct BNode* root;
struct BNode* first;
int cursize;
}BTree;
typedef struct
{
struct BNode* pnode; //
int index; //
bool tag; //
}Result;
BNode* Buynode()
{
BNode* s = (BNode*)malloc(sizeof(BNode));
if (nullptr == s) exit(1);
memset(s, 0, sizeof(BNode));
return s;
}
BNode* BuyLeaf()
{
BNode* s = Buynode();
s->parent = nullptr;
s->utype = LEAF;
return s;
}
BNode* BuyBrchnode()
{
BNode* s = Buynode();
s->parent = nullptr;
s->utype = BRCH;
return s;
}
void Init_BTree(BTree& tree)
{
tree.root = nullptr;
tree.first = nullptr;
tree.cursize = 0;
}
BNode* MakeRoot(const KeyType kx, BNode* left, BNode* right)
{
BNode* s = Buynode();
s->utype = BRCH;
s->num = 1;
s->parent = nullptr;
s->key[1] = kx;
s->sub[0] = left;
if (left != nullptr) left->parent = s;
s->sub[1] = right;
if (right != nullptr) right->parent = s;
return s;
}
Result FindLeaf(BNode* ptr, KeyType kx)
{
Result res = { nullptr,-1,false };
BNode* p = ptr;
while (p != nullptr && p->next != nullptr && kx > p->key[p->num - 1])
{
p = p->next;
}
if (p == nullptr) return res;
int pos = p->num - 1;
while (pos >= 0 && kx < p->key[pos])
{
--pos;
}
res.pnode = p;
res.index = pos;
if (pos < 0 && p->prev != nullptr)
{
res.pnode = p->prev;
res.index = p->prev->num - 1;
}
else if (pos >= 0 && kx == p->key[pos])
{
res.tag = true;
}
return res;
}
Result FindRoot(BNode* ptr, KeyType kx)
{
Result res = { nullptr,-1,false };
BNode* p = ptr;
while (p != nullptr && p->utype == BRCH)
{
p->key[0] = kx;
int i = p->num;
while (kx < p->key[i]) --i;
p = p->sub[i];
}
res = FindLeaf(p, kx);
return res;
}
void Insert_Leaf_Item(BNode *ptr,int pos,KeyType kx, Record *rec)
{
for (int i = ptr->num - 1; i > pos; --i)
{
ptr->key[i + 1] = ptr->key[i];
ptr->recptr[i + 1] = ptr->recptr[i];
}
ptr->key[pos + 1] = kx;
ptr->recptr[pos + 1] = rec;
ptr->num += 1;
}
KeyType Move_Leaf_Item(BNode* s, BNode* ptr)
{
for (int i = 0, j = LEAFMIN; j < ptr->num; ++i, ++j)
{
s->key[i] = ptr->key[j];
s->recptr[i] = ptr->recptr[j];
}
s->num = LEAFMIN;
ptr->num = LEAFMIN;
s->parent = ptr->parent;
s->next = ptr->next;
s->prev = ptr;
ptr->next = s;
if (s->next != nullptr)
{
s->next->prev = s;
}
return s->key[0];
}
void Insert_Brch_Item(BNode* ptr, int pos, KeyType kx, BNode* right)
{
for (int i = ptr->num; i > pos; --i)
{
ptr->key[i + 1] = ptr->key[i];
ptr->sub[i + 1] = ptr->sub[i];
}
ptr->key[pos + 1] = kx;
ptr->sub[pos + 1] = right; // right->parent;
ptr->num += 1;
}
KeyType Move_Brch_Item(BNode* s, BNode* ptr)
{
for (int i = 0, j = LEAFMIN + 1; j <= ptr->num; ++i, ++j)
{
s->key[i] = ptr->key[j];
s->sub[i] = ptr->sub[j];
if (s->sub[i] != nullptr) // ptr leaf . brch;
{
s->sub[i]->parent = s;
}
}
s->num = LEAFMIN;
ptr->num = LEAFMIN;
s->parent = ptr->parent;
return s->key[0];
}
BNode* Splice_Brch(BNode* ptr)
{
BNode* s = BuyBrchnode();
KeyType kx = Move_Brch_Item(s, ptr);
if (ptr->parent == nullptr)
{
return MakeRoot(kx, ptr, s);
}
BNode* pa = ptr->parent;
int pos = pa->num;
pa->key[0] = kx; //
while (pos > 0 && kx < pa->key[pos]) { --pos; }
Insert_Brch_Item(pa, pos,kx, s);
if (pa->num > LEAFMAX)
{
return Splice_Brch(pa);
}
else
{
return nullptr;
}
}
BNode* Splice_Leaf(BNode* ptr)
{
BNode* s = BuyLeaf();
KeyType kx = Move_Leaf_Item(s, ptr);
if (ptr->parent == nullptr)
{
return MakeRoot(kx, ptr, s);
}
BNode* pa = ptr->parent;
int pos = pa->num;
pa->key[0] = kx; //
while (pos > 0 && kx < pa->key[pos]) { --pos; }
Insert_Brch_Item(pa, pos, kx, s);
if (pa->num > BRCHMAX)
{
return Splice_Brch(pa);
}
else
{
return nullptr;
}
}
bool Insert(BTree& tree, KeyType kx, Record* rec)
{
if (tree.root == nullptr)
{
BNode* s = BuyLeaf();
s->key[0] = kx;
s->recptr[0] = rec;
s->num = 1;
tree.root = tree.first = s;
return true;
}
Result resr = FindRoot(tree.root, kx);
Result resf = FindLeaf(tree.first, kx);
if (resf.pnode == nullptr)
{
cout << "Btree struct error " << endl;
return false;
}
if (resf.tag)
{
cout << " xxx " << endl;
return false;
}
BNode *ptr = resf.pnode;
int pos = resf.index;
Insert_Leaf_Item(ptr, pos, kx, rec);
if (ptr->num > LEAFMAX)
{
BNode* newroot = Splice_Leaf(ptr);
if (newroot != nullptr)
{
tree.root = newroot;
}
}
return true;
}
int main()
{
int ar[] = { 23,33,12,10,48,50 };
int n = sizeof(ar) / sizeof(ar[0]);
BTree myt;
Init_BTree(myt);
int i = 0;
while (i < n)
{
Insert(myt, ar[i], nullptr);
++i;
}
return 0;
}
B* 树
B* 树仅仅是在B+树的基础上,在某叶节点满了的情况下,不是直接进行分裂,而是将数据向前驱叶子结点迁移一位,将空间利用率提高
bool Move_Left_Right(BNode* ptr)
{
bool res = false;
BNode* left = ptr->prev;
BNode* right = ptr->next;
if (left != nullptr && left->num < LEAFMAX)
{
res = true;
}
else if (right != nullptr && right->num < LEAFMAX)
{
res = true;
}
return res;
}
bool Insert(BTree& tree, KeyType kx, Record* rec)
{
if (tree.root == nullptr)
{
BNode* s = BuyLeaf();
s->key[0] = kx;
s->recptr[0] = rec;
s->num = 1;
tree.root = tree.first = s;
return true;
}
Result resr = FindRoot(tree.root, kx);
Result resf = FindLeaf(tree.first, kx);
if (resf.pnode == nullptr)
{
cout << "Btree struct error " << endl;
return false;
}
if (resf.tag)
{
cout << " xxx " << endl;
return false;
}
BNode* ptr = resf.pnode;
int pos = resf.index;
Insert_Leaf_Item(ptr, pos, kx, rec);
if (ptr->num > LEAFMAX)
{
if (!Move_Left_Right(ptr))
{
BNode* newroot = Splice_Leaf(ptr);
if (newroot != nullptr)
{
tree.root = newroot;
}
}
}
return true;
}