B树c++实现
第一次实现这么长的代码,从两个地方看的,看了蛮久了,都快背下来了-_-||,记录一下,有点乱
1.插入操作是在这看的,代码基本一样的,作者叫caleblbaker,github上找的,github上还有别人的,但是有些太高级了,我还不会(这里面也有删除但是我没看懂)https://github.com/CalebLBaker/b-tree
2. 删除是在这看的,好像是印度人的网站,代码基本一样的(这里面也有插入)https://www.geeksforgeeks.org/delete-operation-in-b-tree/
找了有些别的地方的代码好像有错误,所以找了这两个地方对照着看,有翻译软件可以不用看英语啦,哈哈
//btree.h
#include<iostream>
template <typename T>
struct BNode//一个节点中包含4个数据
{
T* key;
BNode<T>** child;
int size;//当前节点中key的数量
bool leaf;//是否为叶结点
};
template <typename T>
class BTree
{
BNode<T>* root;//根节点
int mindegeree;//一个节点中key和child的数量,key的数量最多为2*mindegeree-1,最少为mindegeree-1
//child的数量比key多1
void initializeNode(BNode<T>*&);//因为要初始化root,所以用引用,不然就初始化root的拷贝了
void freeNode(BNode<T>*);//释放所有节点
void traverse(BNode<T>*);//遍历输出
void nodeInsert(BNode<T>*, T);//在一个节点中插入,不移动节点
int findIndex(BNode<T>*, T);//返回一个节点中大于等于T的索引
void splitchild(BNode<T>*, int);//当插入路径的节点的size满的话就分裂成两个
T getpred(BNode<T>*, int);//得到比这个节点的值小的最大值(前继)
T getsucc(BNode<T>*, int);//得到比这个节点的值大的最小值(后继)
void removefromleaf(BNode<T>*, int);//从叶结点删除
void removefromnonleaf(BNode<T>* , int);//从非叶结点删除
void borrowfromleft(BNode<T>*, int);//左兄弟节点的大小size大于等于mindegree时,借用左兄弟的值
void borrowfromright(BNode<T>*, int);//右兄弟节点的大小size大于等于mindegree时,借用右兄弟的值
void merge(BNode<T>*, int);//当左右兄弟节点的大小size都小于mindegeree时,合并左兄弟或者右兄弟
void fill(BNode<T>*, int);//保证删除时,其删除路径的大小size要大于等于mindegree
void insert(BNode<T>*&, T);
//插入操作,插入时采取主动分裂的方法,如果路径上的节点的size满的话,
//就主动分裂(也可以和remove一样再加两个函数,移动多余的key到兄弟节点中,我当时没想到),
//再将节点往下迭代,就能防止树一直往上分裂了。要更新root,所以要用引用。
void remove(BNode<T>*&, T);
//删除操作,删除时采取主动补齐的方法,如果路径上的节点的size小于mindegeree的话,就将节点的size补齐,
//要么borrowfromleft要么borrowfromright,要么merge树的根的大小为0时,更新root为其child,所以要用引用
public:
BTree(int i);
~BTree<T>();
void insert(T k)
{
insert(root, k);
}
void remove(T k)
{
remove(root, k);
}
void traverse()
{
traverse(root);
}
};
template <typename T>
BTree<T>::BTree(int i):mindegeree(i),root(nullptr)
{
initializeNode(root);
root->leaf = true;
}
template <typename T>
BTree<T>::~BTree<T>()
{
freeNode(root);
}
template<typename T>
void BTree<T>::initializeNode(BNode<T>*& curr)
{
curr = new BNode<T>();//引用的用处,初始化根节点
curr->key = new T[2 * mindegeree - 1];
curr->child = new BNode<T> * [2 * mindegeree];
curr->size = 0;
}
template<typename T>
void BTree<T>::freeNode(BNode<T>* root)
{
if (!root->leaf)
for (int i = 0; i <= root->size; ++i)
{
freeNode(root->child[i]);
}
delete[] root->key;
delete[] root->child;
delete root;
}
template<typename T>
void BTree<T>::traverse(BNode<T>* root)
{
if (root->leaf)
for (int i = 0; i < root->size; ++i)
std::cout << root->key[i] << " ";
else
for (int i = 0; i <= root->size; ++i)
{
traverse(root->child[i]);
if (i != root->size)
std::cout << root->key[i] << " ";
}
}
template<typename T>
void BTree<T>::nodeInsert(BNode<T>* curr, T k)
{
int index = findIndex(curr, k);
if (k == curr->key[index])
return;
for (unsigned i = curr->size; i >= index+1; --i)
{
curr->key[i] = curr->key[i-1];
if (!curr->leaf)
curr->child[i + 1] = curr->child[i];
}
curr->key[index] = k;
++curr->size;
}
template<typename T>
int BTree<T>::findIndex(BNode<T>* curr, T k)
{
int i = 0;
for (; i < curr->size && k > curr->key[i]; ++i)
;
return i;
}
template<typename T>
void BTree<T>::splitchild(BNode<T>* parent, int i)
{
BNode<T>* child = parent->child[i];
BNode<T>* sibling = nullptr;
initializeNode(sibling);
sibling->leaf = child->leaf;
for (int index = 0; index < mindegeree - 1; ++index)
{
sibling->key[index] = child->key[index + mindegeree];
child->key[index + mindegeree] = 0;
if (!child->leaf)
{
sibling->child[index] = child->child[index + mindegeree];
child->child[index + mindegeree] = nullptr;
}
}
if (!child->leaf)
{
sibling->child[mindegeree - 1] = child->child[2 * mindegeree - 1];
child->child[2 * mindegeree - 1] = nullptr;
}
sibling->size += mindegeree - 1;
child->size -= mindegeree - 1;
nodeInsert(parent, child->key[mindegeree - 1]);
parent->child[i + 1] = sibling;
--child->size;
}
template<typename T>
void BTree<T>::insert(BNode<T>*& root, T k)//要用引用,不然更改不了root
{
if (root->size == 2 * mindegeree - 1)
{
BNode<T>* newRoot = nullptr;
initializeNode(newRoot);
newRoot->leaf = false;
newRoot->child[0] = root;
root = newRoot;//引用的用处
splitchild(newRoot, 0);
}
BNode<T>* curr = root;
while (!curr->leaf)
{
int i = findIndex(curr, k);
if (k == curr->key[i])
return;
else
if (curr->child[i]->size == 2 * mindegeree - 1)
{
splitchild(curr, i);
if (k > curr->child[i]->key[mindegeree - 1])
++i;
}
curr = curr->child[i];
}
nodeInsert(curr, k);
}
template<typename T>
T BTree<T>::getpred(BNode<T>* root, int i)
{
BNode<T>* curr = root->child[i];
while (!curr->leaf)
curr = curr->child[curr->size];
return curr->key[curr->size - 1];
}
template<typename T>
T BTree<T>::getsucc(BNode<T>* root, int i)
{
BNode<T>* curr = root->child[i + 1];
while (!curr->leaf)
curr = curr->child[0];
return curr->key[0];
}
template<typename T>
void BTree<T>::merge(BNode<T>* curr, int i)
{
BNode<T>* child = curr->child[i];
BNode<T>* sibling = curr->child[i + 1];
child->key[child->size] = curr->key[i];
if (!child->leaf)
{
child->child[child->size + 1] = sibling->child[0];
sibling->child[0] = nullptr;
}
++child->size;
for (int ci = child->size, si = 0; si < sibling->size; ++ci, ++si)
{
child->key[ci] = sibling->key[si];
sibling->key[si] = 0;
if (!child->leaf)
{
child->child[ci + 1] = sibling->child[si+1];
sibling->child[si+1] = nullptr;
}
}
child->size += sibling->size;
delete[] sibling->key;
delete[] sibling->child;
delete sibling;
while (i < curr->size-1)
{
curr->key[i] = curr->key[i + 1];
if (!curr->leaf)
curr->child[i + 1] = curr->child[i + 2];
++i;
}
if(!curr->leaf)
curr->child[curr->size] = nullptr;
--curr->size;
}
template<typename T>
void BTree<T>::removefromleaf(BNode<T>* leaf, int i)
{
while (i < leaf->size-1)
{
leaf->key[i] = leaf->key[i + 1];
++i;
}
--leaf->size;
if (leaf->size == 0)
{
delete[] leaf->key;
delete[] leaf->child;
delete leaf;
leaf = nullptr;
}
}
template<typename T>
void BTree<T>::removefromnonleaf(BNode<T>* curr, int i)
{
T value = curr->key[i];
if (curr->child[i]->size >= mindegeree)
{
T pred = getpred(curr, i);
curr->key[i] = pred;
remove(curr->child[i], pred);
}
else if (curr->child[i + 1]->size >= mindegeree)
{
T succ = getsucc(curr, i);
curr->key[i] = succ;
remove(curr->child[i + 1], succ);
}
else
{
merge(curr, i);
if (curr->size == 0)
{
BNode<T>* p = curr;
curr = curr->child[i];
delete[] p->key;
delete[] p->child;
delete p;
p = nullptr;
}
remove(curr, value);
}
}
template<typename T>
void BTree<T>::borrowfromleft(BNode<T>* curr, int i)
{
BNode<T>* child = curr->child[i];
BNode<T>* leftsibling = curr->child[i - 1];
for (int ci = child->size; ci > 0; --ci)
{
child->key[ci] = child->key[ci-1];
if (!child->leaf)
child->child[ci + 1] = child->child[ci];
}
if (!child->leaf)
child->child[1] = child->child[0];
child->key[0] = curr->key[i-1];
int size = leftsibling->size;
if (!child->leaf)
{
child->child[0] = leftsibling->child[size];
leftsibling->child[size] = nullptr;
}
++child->size;
curr->key[i-1] = leftsibling->key[size-1];
leftsibling->key[size] = 0;
--leftsibling->size;
}
template<typename T>
void BTree<T>::borrowfromright(BNode<T>* curr, int i)
{
BNode<T>* child = curr->child[i];
BNode<T>* rightsibling = curr->child[i + 1];
child->key[child->size] = curr->key[i];
if (!child->leaf)
child->child[child->size + 1] = rightsibling->child[0];
++child->size;
curr->key[i] = rightsibling->key[0];
for (int ri = 0; ri < rightsibling->size - 1; ++ri)
{
rightsibling->key[ri] = rightsibling->key[ri + 1];
if (!child->leaf)
rightsibling->child[ri] = rightsibling->child[ri + 1];
}
if (!child->leaf)
{
rightsibling->child[rightsibling->size - 1] = rightsibling->child[rightsibling->size];
rightsibling->child[rightsibling->size];
}
--rightsibling->size;
}
template<typename T>
void BTree<T>::fill(BNode<T>* root, int i)
{
if (i > 0 && root->child[i - 1]->size >= mindegeree)
borrowfromleft(root, i);
else if (i < root->size && root->child[i + 1]->size >= mindegeree)
borrowfromright(root, i);
else
{
if (i != root->size)
merge(root, i);
else
merge(root, i - 1);
}
}
template<typename T>
void BTree<T>::remove(BNode<T>*& root, T k)
{
if (root->size == 0)
root = root->child[0];//引用的用处,改变根节点
BNode<T>* curr = root;
int i = findIndex(root, k);
if (i < root->size && k == root->key[i])
{
if (root->leaf)
removefromleaf(root, i);
else
removefromnonleaf(root, i);
}
else
{
if (root->leaf)
{
std::cout << "dont exist" << std::endl;
return;
}
bool flag = (i == root->size) ? true : false;
if (root->child[i]->size < mindegeree)
{
fill(root, i);
}
if (flag && i > root->size)
{
remove(root->child[i - 1], k);
}
else
remove(root->child[i], k);
}
}
//btree.cpp
#include"btree.h"
int main()
{
BTree<int> t(3);
t.insert(5);
t.insert(25);
t.insert(45);
t.insert(65);
t.insert(85);
t.insert(95);
t.insert(10);
t.insert(15);
t.insert(20);
t.insert(30);
t.insert(50);
t.insert(55);
t.insert(60);
t.insert(70);
t.insert(22);
t.insert(24);
t.insert(26);
t.insert(28);
t.insert(32);
t.insert(34);
t.insert(23);
t.insert(61);
t.insert(62);
t.insert(63);
t.traverse();
std::cout << std::endl;
t.remove(15);
t.remove(25);
t.remove(45);
t.remove(28);
t.remove(25);
t.remove(45);
t.traverse();
return 0;
}
## 有人找到B+树的c++实现能告诉一下我吗?我没找到o(╥﹏╥)o