设计思路:
使用C++中的模板类编程,B+树的存储支持所有数据类型,包括用户自定义类型。
使用纯虚基类,使得B+树中的叶结点与内部结点继承自同一类,便于维护与管理,避免为保证统一而扩充结点导致的空间浪费,利用多态性在运行时确定结点类型。
叉数和类型都作为参数传入。
BPlusTree类维护了结点类型、叉数等信息以及插入、删除、查找等方法。
接口函数通过调用组织B+树类提供的函数,封装后供其它模块调用。
向外提供的接口:
执行创建操作:
根据传入的表名和类型名、类型大小,计算叉数,创建B+树文件,存入叉数和类型名;
执行查询操作:
查询等于,直接调用等值查找;
查询不等于,不通过B+树;
查询大于,找到第一个等于的值,然后沿底部的链表向右把后面的偏移量都存入缓冲区;
查询大于等于,找到第一个等于的值,然后沿底部的链表向右把第一个的偏移量和后面的偏移量都存入缓冲区;
查询大于,找到第一个等于的值,然后沿底部的链表向左把前面的偏移量都存入缓冲区;
查询大于等于,找到第一个等于的值,然后沿底部的链表向左把第一个的偏移量和前面的偏移量都存入缓冲区;
执行插入操作:
根据表名打开对应B+树文件,直接调用插入方法;
执行删除操作:
首先执行查询操作,将符合条件的删除值对应偏移量传出,然后再调用删除方法更新B+树;
执行创建索引操作:
根据索引名新建文件,将该表已有的属性及其偏移量,从底层通过调用insert方法建立B+树,并存入文件,其余使用和基于主键的B+树类似;
删除索引/表:
直接删除对应的B+树文件;
判断是否违反约束:
主要判断主码是否唯一;
类似于等值查找,在非叶结点和叶结点上,一旦读到相同的值,立即返回false;
5.4.5 B+树主要方法:
树的基本操作:
void insert(T x,Index y);
void delete(T x);
bool isKey(T x);
int find(T x);
持久化存储:
void load();
void save();
实现算法:
删除插入算法参考了mysql的innodb引擎中的B+树。
载入B+树:
按照格式化顺序,把读到的文件划分为一个个字符串,并对每个字符串进行相应的映射以及格式转换。第一个读到的结点被作为根结点。
#ifndef _BPLUSTREE_H
#define _BPLUSTREE_H
#include<iostream>
#include <fstream>
#include<string>
template<typename T>
class BPlusTree
{
private:
std::string TYPE;
int RANK;
int MINSIZE;
std::string tableName;
typedef enum { nonleaf, leaf}type;
typedef enum { ins, del }op;
typedef int Index;
class treeNode {
public:
Index id;
Index parent;
int size;
virtual type getType()const = 0; //得到类型:叶结点、内部结点
virtual T getKey(int i)const = 0; //得到下标为i的key
virtual void setKey(T x, int i) = 0; //设置下标为i的key值
virtual void setChild(Index t, int i) { }
virtual void setBlock(int num, int i) { }
virtual void setNext(Index t) { }
virtual void setLast(Index t) { }
virtual Index getChild(int i)const { return -1; }
virtual Index getNext()const { return -1; }
virtual Index getLast()const { return -1; }
virtual int getBlock(int i)const { return 0; }
};
class internalNode :public treeNode {
public:
T* key;
Index* child;
virtual type getType()const { return nonleaf; }
virtual T getKey(int i)const { return key[i]; }
virtual void setKey(T x, int i) { key[i] = x; }
virtual void setChild(Index t, int i) { child[i] = t; }
virtual Index getChild(int i)const { return child[i]; }
internalNode(int RANK, int size = 1) {
key = new T[RANK];
child = new Index[RANK + 1];
this->size = size;
for (int i = 0; i < RANK + 1; i++)child[i] = -1;
}
virtual ~internalNode() { };
};
class leafNode :public treeNode {
public:
T* key;
Index next;
Index last;
int* blockNum;
virtual type getType()const { return leaf; }
virtual T getKey(int i)const { return key[i]; }
virtual void setKey(T x, int i) { key[i] = x; }
virtual void setBlock(int num, int i) { blockNum[i] = num; }
virtual int getBlock(int i)const { return blockNum[i]; }
virtual void setNext(Index t) { next = t; }
virtual void setLast(Index t) { last = t; }
virtual Index getNext()const { return next; }
virtual Index getLast()const { return last; }
leafNode(int RANK,int size = 1) { key = new T[RANK]; blockNum = new int[RANK]; this->size = size; next = -1; }
virtual ~leafNode() { };
};
treeNode* root;
leafNode* childNode;
void insertIntoLeaf(leafNode* p, int i, T x, int y) {
while (i >= 1 && x <= p->getKey(i - 1)) {
p->setKey(p->getKey(i - 1), i);
p->setBlock(p->getBlock(i - 1), i);
i--;
}
//找到插入的位置
p->setKey(x, i);
p->setBlock(y, i);
p->size++;
return;
}
T findKey(treeNode* t) {
while (t->getType() == nonleaf) {
t = node[t->getChild(0)];
}
return t->getKey(0);
}
T findNextKey(Index t) {
while (t->getType() == nonleaf) {
t = t->getChild(0);
}
return t->getKey(1);
}
void updateIndex(treeNode* p, T x) {
if (!p)return;
if (p->parent == -1)return;
internalNode* t = static_cast<internalNode*>(node[p->parent]);
while (t) {
if (x < t->getKey(0)) {
if (t->parent != -1)t = static_cast<internalNode*>(node[t->parent]);
else break;
}
else {
bool flag = false;
for (int i = 0; i < t->size; i++) {
if (x == t->key[i]) {
t->key[i] = findKey(node[t->child[i + 1]]);
flag = true;
break;
}
}
if (flag)break;
else if (t->parent != -1)t = static_cast<internalNode*>(node[t->parent]);
else break;
}
}
return;
}
void updateIndex(treeNode* p, T x, T y) {
if (!p) {
return;
}
Index index = p->parent;
if (p->parent == -1) {
return;
}
internalNode* t = static_cast<internalNode*>(node[p->parent]);
while (t) {
if (y < t->getKey(0)) {
index = t->parent;
if(index!=-1)t = static_cast<internalNode*>(node[index]);
else break;
}
else {
bool flag = false;
for (int i = 0; i < t->size; i++) {
if (y == t->key[i]) {
t->key[i] = x;
flag = true;
break;
}
}
if (flag)break;
index = t->parent;
if (index != -1)t = static_cast<internalNode*>(node[index]);
else break;
}
}
return;
}
void updateChild(internalNode* t, T z)
{
//更新父结点的孩子结点
if (z < t->key[0]) {
for (int i = 0; i < t->size; i++) {
t->key[i] = t->key[i + 1];
t->child[i] = t->child[i + 1];
}
t->child[t->size] = t->child[t->size + 1];
}
else {
for (int i = 0; i < t->size + 1; i++) {
if (z == t->key[i]) {//t是第i + 1个孩子
for (int j = i; j < t->size; j++) {
t->key[j] = t->key[j + 1];
}
for (int j = i + 1; j < t->size + 1; j++) {
t->child[j] = t->child[j + 1];
}
return;
}
}
}
}
leafNode* findLeafNode(T x) {
int count = 0;
treeNode *p = root;
Index j = 1;
if (!p)return nullptr;
while (p->getType() == nonleaf) {
//在已知p为内部结点时,向下造型为内部结点
internalNode* t = dynamic_cast<internalNode*>(p);
if (x < t->getKey(0)) {
j = t->getChild(0);
p = node[j];
}
else {
for (int i = 0; i < t->size - 1; i++) {
if (x >= t->getKey(i) && x < t->getKey(i + 1)) {
j = t->child[i + 1];
p = node[j];
break;
}
}
if (x >= t->getKey(t->size - 1)) {
j = t->child[t->size];
p = node[j];
}
}
}
return static_cast<leafNode*>(p);
}
Index findLeafNode(T x, op type) { //找到x所在的叶结点
treeNode *p = root;
Index j = 1;
if (!p)return -1;
while (p->getType() == nonleaf) {
//在已知p为内部结点时,向下造型为内部结点
internalNode* t = dynamic_cast<internalNode*>(p);
if (x < t->getKey(0)) {
j = t->getChild(0);
p = node[j];
}
else {
for (int i = 0; i < t->size - 1; i++) {
if (x > t->getKey(i) && x < t->getKey(i + 1)) {
j = t->child[i + 1];
p = node[j];
break;
}
else if (x == t->getKey(i)) {
if (type == ins)return -1;
else if (type == del) {
j = t->child[i + 1];
p = node[j];
break;
}
}
}
if (x > t->getKey(t->size - 1)) {
j = t->child[t->size];
p = node[j];
}
else if (x == t->getKey(t->size - 1)) {
if (type == ins)return -1;
else if (type == del) {
j = t->child[t->size];
p = node[j];
}
}
}
}
return j;
}
treeNode* queue[10000];
int front, rear;
void enqueue(treeNode* t)
{
front = (front + 1) % 10000;
queue[front] = t;
}
treeNode* dequeue()
{
rear = (rear + 1) % 10000;
return queue[rear];
}
treeNode* node[30000];
int cnt;
public:
BPlusTree(int r,std::string name,std::string type) {
cnt = 0;
RANK = r;
tableName = name;
MINSIZE = ((RANK + 1) >> 1);
root = nullptr; front = rear = 0;
childNode = new leafNode(1);
node[cnt] = childNode;
TYPE = type;
childNode->id = cnt;
cnt++;
}
~BPlusTree() {}
bool isKey(T x) {
if (!this)return false;
if (!root) {
return false;
}
//找到叶结点
Index index = findLeafNode(x, ins);
if (index == -1)return true;
leafNode* p = static_cast<leafNode*>(node[index]);
if (!p)return true;
for (int j = 0; j < p->size; j++) {
if (x == p->getKey(j)) {
return true;
}
}
return false;
}
void insert(T x, int y) {
if (!root) {
root = new leafNode(1);
root->id = cnt;
node[cnt] = root;
childNode->next = cnt;
childNode->last = -1;
root->setKey(x, 0);
root->setBlock(y, 0);
root->setNext(-1);
root->setLast(0);
root->parent = -1;
cnt++;
return;
}
//找到叶结点
Index index = findLeafNode(x, ins);
if (index == -1)return;
leafNode* p = static_cast<leafNode*>(node[index]);
if (!p)return;
for (int j = 0; j < p->size; j++) {
if (x == p->getKey(j)) {
return;
}
}
//叶结点非满,直接插入
if (p->size != RANK) {
insertIntoLeaf(p, p->size, x, y);
}
//叶结点满
else {
//旋转叶结点
if (p->last != 0 && p->last != -1 && node[p->last]->size < RANK) {
// printf("向左借结点\n");
T w = p->key[0];
int count = 1;
node[p->last]->setKey(p->key[0], node[p->last]->size);
node[p->last]->setBlock(p->blockNum[0], node[p->last]->size);
node[p->last]->size++;
bool flag = false;
for (int i = 0; i < RANK; i++) {
if (!flag && i == RANK - 1) {
p->key[i] = x;
p->blockNum[i] = y;
}
else if (x > p->key[count] || flag) {
p->key[i] = p->key[count];
p->blockNum[i] = p->blockNum[count++];
}
else {
p->key[i] = x;
p->blockNum[i] = y;
flag = true;
}
}
T x = p->key[0];
updateIndex(p, x, w);
return;
}
else if (p->next!=-1 &&node[p->next]->size < RANK) {
// printf("向右借结点\n");
T *num = new T[RANK + 1];
int* Block = new int[RANK + 1];
bool flag = false;
int count = 0;
T w = node[p->next]->getKey(0);
for (int i = 0; i < RANK + 1; i++) {
if (!flag&&i == RANK) {
num[i] = x;
Block[i] = y;
}
else if (x > p->key[count] || flag) {
num[i] = p->key[count];
Block[i] = p->blockNum[count++];
}
else {
num[i] = x;
Block[i] = y;
flag = true;
}
}
for (int i = 0; i < RANK; i++) {
p->key[i] = num[i];
p->blockNum[i] = Block[i];
}
for (int i = node[p->next]->size; i > 0; i--) {
node[p->next]->setKey(node[p->next]->getKey(i-1),i);// [i]ge
node[p->next]->setBlock(node[p->next]->getBlock(i - 1), i);
}
node[p->next]->size++;
node[p->next]->setKey(num[RANK],0);
node[p->next]->setBlock(Block[RANK], 0);
T u = node[p->next]->getKey(0);
updateIndex(node[p->next], u, w);
delete[] Block;
delete[] num;
return;
}
//分裂叶结点
//分裂叶结点
//将p分裂
// printf("分裂叶结点\n");
leafNode* newNode = new leafNode(RANK);
node[cnt] = newNode;
newNode->id = cnt;
cnt++;
struct childnode {
T k;
int num;
}*a = new childnode[RANK + 1];
//将所有数据预存在结构数组a中
for (int i = 0; i < RANK; i++) {
if (p->getKey(i) == x) {
return;
}
a[i].k = p->getKey(i);
a[i].num = p->getBlock(i);
}
int j = RANK - 1;
//将新的数据插入数组a
for (; x < a[j].k && j >= 0; j--) {
a[j + 1] = a[j];
}
a[j + 1].k = x;
a[j + 1].num = y;
//将数组a的数据复制到node1和node2中
for (int i = 0; i < MINSIZE; i++) {
p->setKey(a[i].k, i);
p->setBlock(a[i].num, i);
}
p->size = MINSIZE;
int count = 0;
for (int i = MINSIZE; i < RANK + 1; i++) {
newNode->setKey(a[i].k, count);
newNode->setBlock(a[i].num, count++);
}
newNode->size = RANK - MINSIZE + 1;
//维护双向链表
newNode->next = p->next;
newNode->last = p->id;
if (p->next!=-1) {
static_cast<leafNode*>(node[p->next])->last = newNode->id;
}
p->next = newNode->id;
internalNode* parent = nullptr;
internalNode* newNode2 = nullptr;
treeNode** Node = new treeNode*[RANK + 2];
treeNode* t = p;
while (t != nullptr) {
if(t->parent!=-1)parent = static_cast<internalNode*>(node[t->parent]);
else parent = nullptr;
if (!newNode2) {
if (parent) {
leafNode* tmp = static_cast<leafNode*>(node[parent->getChild(0)]);
for (int i = 0; i<parent->size + 2; i++) {
Node[i] = tmp;
if(tmp->next!=-1)tmp = static_cast<leafNode*>(node[tmp->next]);
}
}
else {
Node[0] = t;
Node[1] = newNode;
}
}
else {
if (parent) {
int count = 0;//2
bool flag = false;
internalNode* tmp = nullptr;
for (int i = 0; i <parent->size + 2; i++) {
if (count<parent->size + 1)tmp = static_cast<internalNode*>(node[parent->child[count]]);
if (tmp!=nullptr&&!flag && (newNode2->key[0] < tmp->key[0] || i == parent->size + 1)) {
Node[i] = newNode2;
flag = true;
}
else {
Node[i] = node[parent->child[count++]];
}
}
}
else {
Node[0] = t;
Node[1] = newNode2;
}
}
//case 1: 当前结点是根节点,根节点长高
if (!parent) {
internalNode* r = new internalNode(1);
node[cnt] = r;
r->id = cnt;
cnt++;
for (int i = 0; i < 2; i++) {
r->child[i] = Node[i]->id;
node[r->child[i]]->parent = r->id;
}
r->key[0] = findKey(node[r->child[1]]);
root = r;
root->parent = -1;
break;
}
//case 2 :当前结点的父节点不满
else if (parent->size < RANK) {
// printf("case 2 :当前结点的父节点不满 \n");
for (int i = 0; i < parent->size + 2; i++) {
parent->child[i] = Node[i]->id;
node[parent->child[i]]->parent = parent->id;
}
for (int i = 0; i < parent->size + 1; i++) {
parent->key[i] = findKey(node[parent->child[i + 1]]);
}
parent->size++;
//printf("quit\n");
break;
}
//case 3 :当前父节点已满,分裂父节点
else if (parent->size == RANK) {
// printf("case 3 :当前父节点已满,分裂父节点\n");
newNode2 = new internalNode(RANK - MINSIZE);
node[cnt] = newNode2;
newNode2->id = cnt;
cnt++;
for (int i = 0; i < MINSIZE + 1; i++) {
parent->child[i] = Node[i]->id;
node[parent->child[i]]->parent = parent->id;
}
for (int i = 0; i < MINSIZE; i++) {
parent->key[i] = findKey(node[parent->child[i + 1]]);
}
parent->size = MINSIZE;
int count = 0;
for (int i = MINSIZE + 1; i < RANK + 2; i++) {
newNode2->child[count] = Node[i]->id;
node[newNode2->child[count++]]->parent = newNode2->id;
}
count = 0;
for (int i = MINSIZE + 1; i < RANK + 1; i++) {
newNode2->key[count] = findKey(node[newNode2->child[count + 1]]);
count++;
}
t = parent;
}
}
}
return;
}
void Delete(T x)
{
//找到叶结点
Index index = findLeafNode(x, del);
if (index == -1)return;
leafNode* p = static_cast<leafNode*>(node[index]);
//("index = %d\n", index);
if (!p)return;
T past;//原来的索引值
past = p->key[0];
//找到所在下标
int j = -1;
for (int i = 0; i < p->size; i++) {
if (x == p->getKey(i)) {
j = i;
break;
}
}
//用后面的值填补删除值的位置
if (j == -1) { return; }
for (int i = j + 1; i < p->size; i++) {
p->setKey(p->getKey(i), i - 1);
p->setBlock(p->getBlock(i), i - 1);
}
p->size--;
//删除后大小仍然大于最小值
if (p->size >= MINSIZE) {
// printf("here\n");
if(p->parent!=-1)updateIndex(p, x);//更新值为x的索引
return;//可能影响了父节点的索引
}
else if (p == root) {
if (p->size == 0)root = nullptr;
return;
}
//向左借元素
if (p->last != 0 && node[p->last]->size >MINSIZE) {
// printf("1向左借元素\n");
if(p->parent!=-1)updateIndex(p, x);//更新值为x的索引
for (int i = MINSIZE - 1; i > 0; i--) {
p->key[i] = p->key[i - 1];
p->blockNum[i] = p->blockNum[i - 1];
}//挪出一个位置
p->key[0] = node[p->last]->getKey(node[p->last]->size - 1);
p->blockNum[0] = node[p->last]->getBlock(node[p->last]->size-1);
//将左节点的值放到挪出的位置
T z = p->key[0];//新的索引值
T y = p->key[1];//原来的索引值
node[p->last]->size--;//左节点的大小减一
p->size++;//该结点的大小加一
updateIndex(p, z, y);//将原来的索引值更新为新的索引值
return;
}
//向右借元素
else if (p->next!=-1 &&node[p->next]->size>MINSIZE) {
// printf("1向右借元素\n");
updateIndex(p, x);//更新值为x的索引
T y = node[p->next]->getKey(0);//原来的索引值
T z = node[p->next]->getKey(1);//新的索引值
p->key[MINSIZE - 1] = node[p->next]->getKey(0);//将右结点的元素放到后面
p->blockNum[MINSIZE - 1] = node[p->next]->getBlock(0);
p->size++;//该结点元素数加一
for (int i = 0; i < node[p->next]->size - 1; i++) {
node[p->next]->setKey(node[p->next]->getKey(i + 1),i);
node[p->next]->setBlock(node[p->next]->getBlock(i + 1),i);
}//右结点的元素向左挪动
node[p->next]->size--;//下一个结点数减一
updateIndex(node[p->next], z, y);//将原来的索引值更新为新的索引值
return;
}
else {
internalNode* t = nullptr;//当前结点
//向左合并
int count = 0;
if (p->last != 0 && node[p->last]->size + p->size <= RANK) {
// printf("1向左合并\n");
t = static_cast<internalNode*>(node[p->parent]);
for (int i = node[p->last]->size; i < node[p->last]->size + p->size; i++) {
node[p->last]->setKey(p->key[count],i);
node[p->last]->setBlock(p->blockNum[count++],i);
}//将当前结点的值转移到左节点中
node[p->last]->size = node[p->last]->size + p->size;//更新左节点的大小
//维护双向链表
node[p->last]->setNext(p->next);
if (p->next!=-1) node[p->next]->setLast(p->last);
//更新p的指针,防止空指针
p->parent = -1;
p->next = -1;
p->last = -1;
delete p;
}
//向右合并
else if (p->next!=-1 && node[p->next]->size + p->size <= RANK) {
// printf("1向右合并\n");
count = 0;
past = node[p->next]->getKey(0); //合并前,记录原来的索引值
t = static_cast<internalNode*>(node[node[p->next]->parent]);
for (int i = p->size; i < node[p->next]->size + p->size; i++) {
p->setKey(node[p->next]->getKey(count),i);
p->setBlock(node[p->next]->getBlock(count++),i);
} //将右结点的值转移到当前结点
p->size = node[p->next]->size + p->size;//更新当前结点的大小
//维护双向链表
if (node[p->next]->getNext() != -1)node[node[p->next]->getNext()]->setLast(p->id);
leafNode* tmp = static_cast<leafNode*>(node[p->next]);
p->next = node[p->next]->getNext();
//更新p->next的指针
tmp->parent = -1;
tmp->next = -1;
tmp->last = -1;
delete tmp;
}
t->size--;
//更新
updateChild(t, past);
updateIndex(t, past);
int index = -1;
while (t != nullptr) {
internalNode* parent;
if(t->parent!=-1)parent = static_cast<internalNode*>(node[t->parent]);//计算得到父母
//case 1:当前结点为根节点
else parent = nullptr;
if (!parent) {
if (t->size == 0) {
root = node[t->child[0]];
root->parent = -1;
}
break;
}
//case 2:当前结点大于最小结点数
else if (t->size >= MINSIZE - 1) {
if (index != -1) {
for (int i = index; i < t->size + 1; i++) {
t->child[i] = t->child[i + 1];
}
}
break;
}
//case 3:当前结点小于最小结点数
else if (t->size < MINSIZE - 1) {
// updateChild(t, z);
internalNode* sibling;
//如果邻居的大小大于等于MINSIZE
int last = -1, next = 1, now = 0;
if (t->key[0] >= parent->key[0]) {
for (int i = 0; i < parent->size; i++) {
if (t->key[0] < parent->key[i]) {
last = i - 1;
now = i;
next = i + 1;
break;
}
else if (i == parent->size - 1) {
last = parent->size - 1;
now = parent->size;
next = parent->size + 1;
}
}
}
if (last >= 0) {
sibling = static_cast<internalNode*>(node[parent->child[last]]);
//向左借节点
if (sibling->size >= MINSIZE) {
// printf("向左借元素\n");
for (int i = t->size + 1; i >= 1; i--) {
t->child[i] = t->child[i - 1];
}
for (int i = t->size; i >= 1; i--) {
t->key[i] = t->key[i - 1];
}
t->child[0] = node[sibling->child[sibling->size]]->id;
node[t->child[0]]->parent = t->id;
t->key[0] = findKey(node[t->child[1]]);
//更新父节点
node[t->parent]->setKey(findKey(node[node[t->parent]->getChild(now)]), last);
sibling->child[sibling->size] = -1;
sibling->size--;
t->size++;
break;
}
//与左节点合并
else if (t->size + sibling->size + 1 <= RANK) {
// printf("与左节点合并\n");
int count = 0;
for (int i = sibling->size + 1; i < t->size + sibling->size + 2; i++) {
sibling->child[i] = t->child[count++];
node[sibling->child[i]]->parent = sibling->id;
}
for (int i = sibling->size; i < t->size + sibling->size + 1; i++) {
sibling->key[i] = findKey(node[sibling->child[i + 1]]);
}
sibling->size = t->size + sibling->size + 1;
t->parent = -1;
delete t;
for (int i = now; i < parent->size; i++) {
parent->child[i] = parent->child[i + 1];
}
for (int i = last; i < parent->size - 1; i++) {
parent->key[i] = findKey(node[parent->child[i + 1]]);
}
parent->size--;
t = parent;
}
}
else if (next <= RANK + 1) {
sibling = static_cast<internalNode*>(node[parent->child[next]]);
//向右借结点
if (sibling->size >= MINSIZE) {
// printf("向右借结点\n");
t->child[t->size + 1] = sibling->child[0];
node[t->child[t->size + 1]]->parent = t->id;
t->key[t->size] = findKey(node[t->child[t->size + 1]]);
for (int i = 0; i < sibling->size; i++) {
sibling->child[i] = sibling->child[i + 1];
}
for (int i = 0; i < sibling->size - 1; i++) {
sibling->key[i] = findKey(node[sibling->child[i + 1]]);
}
node[t->parent]->setKey(findKey(node[node[t->parent]->getChild(next)]), now);
sibling->child[sibling->size] = -1;
sibling->size--;
t->size++;
break;
}
//与右结点合并
else if (t->size + sibling->size + 1 <= RANK) {
// printf("与右节点合并\n");
int count = 0;
for (int i = t->size + 1; i < t->size + sibling->size + 2; i++) {
t->child[i] = sibling->child[count++];
node[t->child[i]]->parent = t->id;
}
//count = 0;
for (int i = t->size; i < t->size + sibling->size + 1; i++) {
t->key[i] = findKey(node[t->child[i + 1]]);
}
t->size = t->size + sibling->size + 1;
sibling->parent = -1;
delete sibling;
for (int i = next; i < parent->size; i++) {
parent->child[i] = parent->child[i + 1];
}
for (int i = now; i < parent->size - 1; i++) {
parent->key[i] = findKey(node[parent->getChild(i + 1)]);
}
parent->size--;
t = parent;
}
}
}
}
}
}
void at(int index) {
leafNode* tmp = childNode;
for (int i = 0; i < index + 1; i++) {
tmp = tmp->next;
}
for (int i = 0; i < tmp->size; i++) {
std::cout << tmp->getKey(i) << " ";
}
std::cout << std::endl;
}
std::string getName() //打印出模板参数的类型名
{
return typeid(T).name();
}
void print() {
//printf("sizeof int = %d\n", sizeof(int));
//printf("size = %d\n",sizeof(leafNode));
if (!root)return;
bool flag = false;
treeNode* tmp;
std::cout << RANK << " ";
std::cout << typeid(T).name();
front = (front + 1) % 10000;
queue[front] = root;
int cur = 1;
int curnum = 1;
int nextnum = 0;
while (front != rear) {
rear = (rear + 1) % 10000;
tmp = queue[rear];
if (tmp->getType() == nonleaf) {
std::cout << "[";
internalNode* t = static_cast<internalNode*>(tmp);
curnum--;
std::cout << tmp->getType() << " ";
if (tmp->parent != -1) {
std::cout << node[tmp->parent]->id << " ";
}
else std::cout << "-1 ";
std::cout << t->id << " ";
std::cout << tmp->size << " ";
for (int i = 0; i < tmp->size - 1; i++) {
std::cout << tmp->getKey(i) << " ";
}
std::cout << tmp->getKey(tmp->size - 1) << " ";;
for (int i = 0; i < tmp->size + 1; i++) {
if (i == tmp->size) {
if (t->child[i] != -1) {
std::cout << node[t->child[i]]->id << "]";
front = (front + 1) % 10000;
queue[front] = node[t->child[i]];
nextnum++;
}
else std::cout << "-1]";
}
else {
if (t->child[i] != -1) {
std::cout << node[t->child[i]]->id << " ";
front = (front + 1) % 10000;
queue[front] = node[t->child[i]];
nextnum++;
}
else std::cout << "-1 ";
}
}
if (curnum == 0) {
cur++;
curnum = nextnum;
nextnum = 0;
}
}
else {
std::cout << "[";
std::cout << tmp->getType() << " ";
if (tmp->parent != -1) {
std::cout << node[tmp->parent]->id << " ";
}
else std::cout << "-1 ";
std::cout << tmp->id << " ";
std::cout << tmp->size << " ";
std::cout << tmp->getLast() << " " << tmp->getNext() << " ";
for (int i = 0; i < tmp->size - 1; i++) {
std::cout << tmp->getBlock(i) << " ";
}
std::cout << tmp->getBlock(tmp->size - 1) << " ";
for (int i = 0; i < tmp->size - 1; i++) {
std::cout << tmp->getKey(i) << " ";
}
std::cout << tmp->getKey(tmp->size - 1) << "]";
}
}
}
void save() {
bool flag = false;
treeNode* tmp;
std::ofstream out(tableName+".txt", std::ios_base::out);
out << RANK << " ";
out << TYPE ;
if (!root)return;
front = (front + 1) % 10000;
queue[front] = root;
int cur = 1;
int curnum = 1;
int nextnum = 0;
while (front != rear) {
rear = (rear + 1) % 10000;
tmp = queue[rear];
if (tmp->getType() == nonleaf) {
out << "[";
internalNode* t = static_cast<internalNode*>(tmp);
curnum--;
out << tmp->getType()<<" ";
if (tmp->parent!=-1) {
out << node[tmp->parent]->id<<" ";
}
else out << "-1 ";
out << t->id << " ";
out << tmp->size << " ";
for (int i = 0; i < tmp->size - 1; i++) {
out << tmp->getKey(i)<<" ";
}
out<<tmp->getKey(tmp->size - 1) << " ";;
for (int i = 0; i < tmp->size + 1; i++) {
if (i == tmp->size) {
if (t->child[i] != -1) {
out << node[t->child[i]]->id << "]";
front = (front + 1) % 10000;
queue[front] = node[t->child[i]];
nextnum++;
}
else out << "-1]";
}
else {
if (t->child[i] != -1) {
out << node[t->child[i]]->id << " ";
front = (front + 1) % 10000;
queue[front] = node[t->child[i]];
nextnum++;
}
else out << "-1 ";
}
}
if (curnum == 0) {
cur++;
curnum = nextnum;
nextnum = 0;
}
}
else {
out << "[";
out << tmp->getType() << " ";
if (tmp->parent!=-1) {
out << node[tmp->parent]->id << " ";
}
else out << "-1 ";
out << tmp->id << " ";
out << tmp->size << " ";
out << tmp->getLast() << " " << tmp->getNext() << " ";
for (int i = 0; i < tmp->size - 1; i++) {
out << tmp->getBlock(i) << " ";
}
out << tmp->getBlock(tmp->size - 1) << " ";
for (int i = 0; i < tmp->size - 1; i++) {
out << tmp->getKey(i) << " ";
}
out << tmp->getKey(tmp->size - 1) << "]";
}
}
out.close();
}
void loadFloat(std::string s) {
treeNode* p = nullptr;
int j = 0;
std::string str = "";
int count = 0;
if (s[0] == '0') {
p = new internalNode(RANK);
for (int i = 2; i <= s.length(); i++) {
if (s[i] != ' '&&s[i] != ']'&&s[i] != '['&&i != s.length()) {
str = str + s[i];
}
else {
if (count == 0) {
p->parent = std::atoi(str.c_str());
str = "";
count++;
}
else if (count == 1) {
p->id = std::atoi(str.c_str());
node[p->id] = p;
str = "";
count++;
}
else if (count == 2) {
p->size = std::atoi(str.c_str());
str = "";
count++;
}
else if (count == 3) {
if (getName() == "float") {
p->setKey(std::atof(str.c_str()), j);
str = "";
j++;
}
if (j == p->size) {
j = 0;
count++;
}
}
else if (count == 4) {
p->setChild(std::atoi(str.c_str()), j);
str = "";
j++;
if (j == p->size + 1) {
j = 0;
count = 0;
break;
}
}
}
}
}
else if (s[0] == '1') {
p = new leafNode(RANK);
for (int i = 2; i <= s.length(); i++) {
if (s[i] != ' '&&s[i] != ']'&&s[i] != '['&&i != s.length()) {
str = str + s[i];
}
else {
if (count == 0) {
p->parent = std::atoi(str.c_str());
str = "";
count++;
}
else if (count == 1) {
p->id = std::atoi(str.c_str());
node[p->id] = p;
str = "";
count++;
}
else if (count == 2) {
p->size = std::atoi(str.c_str());
str = "";
count++;
}
else if (count == 3) {
p->setLast(std::atoi(str.c_str()));
str = "";
count++;
}
else if (count == 4) {
p->setNext(std::atoi(str.c_str()));
count++;
str = "";
}
else if (count == 5) {
p->setBlock(std::atoi(str.c_str()), j);
j++;
str = "";
if (j == p->size) {
j = 0;
count++;
}
}
else if (count == 6) {
if (getName() == "float") {
p->setKey(std::atof(str.c_str()), j);
str = "";
j++;
}
str = "";
if (j == p->size) {
j = 0;
count = 0;
break;
}
}
}
}
}
if (!root) {
printf("here\n");
if (p->getType() == nonleaf) {
root = new internalNode(RANK);
root = p;
}
else {
root = new leafNode(RANK);
root = p;
}
}
}
void loadString(std::string s) {
treeNode* p = nullptr;
int j = 0;
std::string str = "";
int count = 0;
if (s[0] == '0') {
p = new internalNode(RANK);
for (int i = 2; i <= s.length(); i++) {
if (s[i] != ' '&&s[i] != ']'&&s[i] != '['&&i != s.length()) {
str = str + s[i];
}
else {
if (count == 0) {
p->parent = std::atoi(str.c_str());
str = "";
count++;
}
else if (count == 1) {
p->id = std::atoi(str.c_str());
node[p->id] = p;
str = "";
count++;
}
else if (count == 2) {
p->size = std::atoi(str.c_str());
str = "";
count++;
}
else if (count == 3) {
if (getName() == "string") {
p->setKey(str, j);
str = "";
j++;
}
if (j == p->size) {
j = 0;
count++;
}
}
else if (count == 4) {
p->setChild(std::atoi(str.c_str()), j);
str = "";
j++;
if (j == p->size + 1) {
j = 0;
count = 0;
break;
}
}
}
}
}
else if (s[0] == '1') {
p = new leafNode(RANK);
for (int i = 2; i <= s.length(); i++) {
if (s[i] != ' '&&s[i] != ']'&&s[i] != '['&&i != s.length()) {
str = str + s[i];
}
else {
if (count == 0) {
p->parent = std::atoi(str.c_str());
str = "";
count++;
}
else if (count == 1) {
p->id = std::atoi(str.c_str());
node[p->id] = p;
str = "";
count++;
}
else if (count == 2) {
p->size = std::atoi(str.c_str());
str = "";
count++;
}
else if (count == 3) {
p->setLast(std::atoi(str.c_str()));
str = "";
count++;
}
else if (count == 4) {
p->setNext(std::atoi(str.c_str()));
count++;
str = "";
}
else if (count == 5) {
p->setBlock(std::atoi(str.c_str()), j);
j++;
str = "";
if (j == p->size) {
j = 0;
count++;
}
}
else if (count == 6) {
if (getName() == "string") {
p->setKey(str, j);
str = "";
j++;
}
str = "";
if (j == p->size) {
j = 0;
count = 0;
break;
}
}
}
}
}
if (!root) {
if (p->getType() == nonleaf) {
root = new internalNode(RANK);
root = p;
}
else {
root = new leafNode(RANK);
root = p;
}
}
}
void loadInt(std::string s) {
treeNode* p = nullptr;
int j = 0;
std::string str = "";
int count = 0;
if (s[0] == '0') {
p = new internalNode(RANK);
for (int i = 2; i <= s.length(); i++) {
if (s[i] != ' '&&s[i]!=']'&&s[i]!='['&&i!=s.length()) {
str = str + s[i];
}
else{
if (count == 0) {
p->parent = std::atoi(str.c_str());
str = "";
count++;
}
else if (count == 1) {
p->id = std::atoi(str.c_str());
node[p->id] = p;
str = "";
count++;
}
else if (count == 2) {
p->size = std::atoi(str.c_str());
str = "";
count++;
}
else if (count == 3) {
if (getName() == "int") {
T x = std::atoi(str.c_str());
p->setKey(x, j);
str = "";
j++;
}
if (j == p->size) {
j = 0;
count++;
}
}
else if (count == 4) {
p->setChild(std::atoi(str.c_str()),j);
str = "";
j++;
if (j == p->size+1) {
j = 0;
count = 0;
break;
}
}
}
}
}
else if (s[0] == '1') {
p = new leafNode(RANK);
for (int i = 2; i <= s.length(); i++) {
if (s[i] != ' '&&s[i] != ']'&&s[i] != '['&&i != s.length()) {
str = str + s[i];
}
else {
if (count == 0) {
p->parent = std::atoi(str.c_str());
str = "";
count++;
}
else if (count == 1) {
p->id = std::atoi(str.c_str());
node[p->id] = p;
str = "";
count++;
}
else if (count == 2) {
p->size = std::atoi(str.c_str());
str = "";
count++;
}
else if (count == 3) {
p->setLast(std::atoi(str.c_str()));
str = "";
count++;
}
else if (count == 4) {
p->setNext(std::atoi(str.c_str()));
count++;
str = "";
}
else if (count == 5) {
p->setBlock(std::atoi(str.c_str()), j);
j++;
str = "";
if (j == p->size) {
j = 0;
count++;
}
}
else if (count == 6) {
if (getName() == "int") {
p->setKey(std::atoi(str.c_str()), j);
str = "";
j++;
}
if (j == p->size) {
j = 0;
count = 0;
break;
}
}
}
}
}
if (!root) {
if (p->getType() == nonleaf) {
root = new internalNode(RANK);
root = p;
}
else {
root = new leafNode(RANK);
root = p;
}
}
}
int equal(T x) { //找到x所在的叶结点
treeNode *p = root;
Index j = 1;
if (!p)return -1;
while (p->getType() == nonleaf) {
//在已知p为内部结点时,向下造型为内部结点
internalNode* t = dynamic_cast<internalNode*>(p);
if (x < t->getKey(0)) {
j = t->getChild(0);
p = node[j];
}
else {
for (int i = 0; i < t->size - 1; i++) {
if (x >= t->getKey(i) && x < t->getKey(i + 1)) {
j = t->child[i + 1];
p = node[j];
break;
}
}
if (x >= t->getKey(t->size - 1)) {
j = t->child[t->size];
p = node[j];
}
}
}
for (int i= 0; i < p->size; i++) {
if (p->getKey(i) == x) {
return p->getBlock(i);
}
}
return -1;
}
void larger(int* buffer,T x) {
int count = 0;
leafNode *p = findLeafNode(x);
while (1) {
for (int i = 0; i < p->size; i++) {
if (p->getKey(i)>x) {
buffer[++count] = p->getBlock(i);
}
}
if(p->next!=-1)p = static_cast<leafNode*>(node[p->next]);
else break;
}
buffer[0] = count;
}
void smaller(int* buffer, T x) {
int count = 0;
leafNode *p = findLeafNode(x);
while (1) {
for (int i = 0; i < p->size; i++) {
if (p->getKey(i)<x) {
buffer[++count] = p->getBlock(i);
}
}
if (p->last != 0)p = static_cast<leafNode*>(node[p->last]);
else break;
}
buffer[0] = count;
}
void largerAndEqual(int* buffer, T x) {
int count = 0;
leafNode *p = findLeafNode(x);
while (1) {
for (int i = 0; i < p->size; i++) {
if (p->getKey(i)>=x) {
buffer[++count] = p->getBlock(i);
}
}
if (p->next != -1)p = static_cast<leafNode*>(node[p->next]);
else break;
}
buffer[0] = count;
}
void smallerAndEqual(int* buffer, T x) {
int count = 0;
leafNode *p = findLeafNode(x);
while (1) {
for (int i = 0; i < p->size; i++) {
if (p->getKey(i)<=x) {
buffer[++count] = p->getBlock(i);
}
}
if (p->last != 0)p = static_cast<leafNode*>(node[p->last]);
else break;
}
buffer[0] = count;
}
void deleteLarger(T x) {
int count = 0;
T buffer[30000];
leafNode *p = findLeafNode(x);
while (1) {
for (int i = 0; i < p->size; i++) {
if (p->getKey(i)>x) {
buffer[++count] = p->getKey(i);
}
}
if (p->next != -1)p = static_cast<leafNode*>(node[p->next]);
else break;
}
for (int i = 1; i <= count; i++) {
Delete(buffer[i]);
}
}
void deleteSmaller(T x) {
int count = 0;
T buffer[30000];
leafNode *p = findLeafNode(x);
while (1) {
for (int i = 0; i < p->size; i++) {
if (p->getKey(i)<x) {
buffer[++count] = p->getKey(i);
}
}
if (p->last != 0)p = static_cast<leafNode*>(node[p->last]);
else break;
}
for (int i = 1; i <= count; i++) {
Delete(buffer[i]);
}
}
void deleteLargerAndEqual(T x) {
int count = 0;
T buffer[30000];
leafNode *p = findLeafNode(x);
while (1) {
for (int i = 0; i < p->size; i++) {
if (p->getKey(i)>=x) {
buffer[++count] = p->getKey(i);
}
}
if (p->next != -1)p = static_cast<leafNode*>(node[p->next]);
else break;
}
for (int i = 1; i <= count; i++) {
Delete(buffer[i]);
}
}
void deleteSmallerAndEqual(T x) {
int count = 0;
T buffer[30000];
leafNode *p = findLeafNode(x);
while (1) {
for (int i = 0; i < p->size; i++) {
if (p->getKey(i)<=x) {
buffer[++count] = p->getKey(i);
}
}
if (p->last != 0)p = static_cast<leafNode*>(node[p->last]);
else break;
}
for (int i = 1; i <= count; i++) {
Delete(buffer[i]);
}
}
};
#endif
main,cpp
#include"BPlusTree.h"
#include<stdlib.h>
#include<time.h>
int main()
{
srand(unsigned(time(nullptr)));
BPlusTree<int> *p = new BPlusTree<int>(10,"dB1","int");
for (int i = 0; i <10000; i++) {
// int x = rand() % 10000000;
int x = i;
p->insert(x,i);
}
p->print();
p->save();
for (int i = 0; i <10000; i++) {
// int x = rand() % 10000000;
int x = i;
p->Delete(x);
}
printf("\n-------------------------------\n");
p->print();
system("pause");
}
部分接口
#define _CRT_SECURE_NO_WARNINGS
#include "BPlusTree.h"
#include<cstdlib>
#include<cstdio>
#include<iostream>
#include<fstream>
#include<string>
BPlusTree<int> *p1 = nullptr;
BPlusTree<float> *p2 = nullptr;
BPlusTree<std::string> *p3 = nullptr;
std::string type = "";
int RANK;
//删除返回blockNum
//int* select(std::string tableName,int operation,T element);
void selectInt(int *buffer, std::string tableName, int op, int element)
{
std::string path = tableName;
load(path);
if (op == 0) {//等于
int ans = p1->equal(element);
buffer[0] = 1;
buffer[1] = ans;
}
else if (op == 1) {//大于
p1->larger(buffer, element);
}
else if (op == 2) {//大于等于
p1->largerAndEqual(buffer, element);
}
else if (op == 3) {//小于
p1->smaller(buffer, element);
}
else if (op == 4) {//小于等于
p1->smallerAndEqual(buffer, element);
}
}
void selectFloat(int *buffer, std::string tableName, int op, float element)
{
std::string path = tableName;
load(path);
if (op == 0) {//等于
int ans = p1->equal(element);
buffer[0] = 1;
buffer[1] = ans;
}
else if (op == 1) {//大于
p2->larger(buffer, element);
}
else if (op == 2) {//大于等于
p2->largerAndEqual(buffer, element);
}
else if (op == 3) {//小于
p2->smaller(buffer, element);
}
else if (op == 4) {//小于等于
p2->smallerAndEqual(buffer, element);
}
}
void selectString(int *buffer, std::string tableName, int op, std::string element)
{
std::string path = tableName;
load(path);
if (op == 0) {//等于
int ans = p3->equal(element);
buffer[0] = 1;
buffer[1] = ans;
}
else if (op == 1) {//大于
p3->larger(buffer, element);
}
else if (op == 2) {//大于等于
p3->largerAndEqual(buffer, element);
}
else if (op == 3) {//小于
p3->smaller(buffer, element);
}
else if (op == 4) {//小于等于
p3->smallerAndEqual(buffer, element);
}
}
void createTree(std::string tableName, std::string type, int size)
{
RANK = (4096 - 5 * sizeof(int)) / (2 * size);
if (type == "int") {
p1 = new BPlusTree<int>(RANK, tableName, type);
p1->save();
}
else if (type == "float") {
p2 = new BPlusTree<float>(RANK, tableName, type);
p2->save();
}
else if (type == "string") {
p3 = new BPlusTree<std::string>(RANK, tableName, type);
p3->save();
}
}
void deleteInt(std::string tableName, int op, int data)
{
std::string path = tableName;
load(path);
if (op == 0) {//等于
p1->Delete(data);
}
else if (op == 1) {//大于
p1->deleteLarger(data);
}
else if (op == 2) {//大于等于
p1->deleteLargerAndEqual(data);
}
else if (op == 3) {//小于
p1->deleteSmaller(data);
}
else if (op == 4) {//小于等于
p1->deleteSmallerAndEqual(data);
}
p1->save();
}
void deleteFloat(std::string tableName, int op, float data)
{
std::string path = tableName;
load(path);
if (op == 0) {//等于
p2->Delete(data);
}
else if (op == 1) {//大于
p2->deleteLarger(data);
}
else if (op == 2) {//大于等于
p2->deleteLargerAndEqual(data);
}
else if (op == 3) {//小于
p2->deleteSmaller(data);
}
else if (op == 4) {//小于等于
p2->deleteSmallerAndEqual(data);
}
p2->save();
}
void deleteString(std::string tableName, int op, std::string data)
{
std::string path = tableName;
load(path);
if (op == 0) {//等于
p3->Delete(data);
}
else if (op == 1) {//大于
p3->deleteLarger(data);
}
else if (op == 2) {//大于等于
p3->deleteLargerAndEqual(data);
}
else if (op == 3) {//小于
p3->deleteSmaller(data);
}
else if (op == 4) {//小于等于
p3->deleteSmallerAndEqual(data);
}
p3->save();
}
void dropTable(const char* tableName)
{
remove(tableName);
}
//dropTable(string tableName);
BPlusTree<int>* getIndexInt(std::string indexName)
{
int RANK = (4096 - 5 * sizeof(int)) / (2 * sizeof(int));
p1 = new BPlusTree<int>(RANK, indexName + ".txt", "int");
p1->save();
return p1;
}
BPlusTree<float>* getIndexFloat(std::string indexName)
{
int RANK = (4096 - 5 * sizeof(int)) / (2 * sizeof(float));
p2 = new BPlusTree<float>(RANK, indexName + ".txt", "float");
p2->save();
return p2;
}
BPlusTree<std::string>* getIndexString(std::string indexName, int size)
{
int RANK = (4096 - 5 * sizeof(int)) / (2 * size);
p3 = new BPlusTree<std::string>(RANK, indexName + ".txt", "string");
p3->save();
return p3;
}
//select id > 3
//select(std::string tableName, op operation);
bool isKeyInt(std::string tableName, int data)
{
std::string path = tableName;
load(path);
return p1->isKey(data);
}
bool isKeyFloat(std::string tableName, float data)
{
std::string path = tableName;
load(path);// load(path);
return p2->isKey(data);
}
bool isKeyString(std::string tableName, std::string data)
{
std::string path = tableName;
load(path);
if (!p3)std::cout << "no" << std::endl;
return p3->isKey(data);
}
void insertInt(std::string tableName, int data, int offset)
{
std::string path = tableName;
load(path);
p1->insert(data, offset);
p1->save();
}
void insertFloat(std::string tableName, float data, int offset)
{
std::string path = tableName;
load(path);
p2->insert(data, offset);
p2->save();
}
void insertString(std::string tableName, std::string data, int offset)
{
std::string path = tableName;
load(path);
p3->insert(data, offset);
p3->save();
}