B+樹(插入,非惰性刪除)
設計思路:
使用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();
}