#include <iostream>
struct Node{
int n=0, t;
int* key;
bool leaf;
Node** cNs;
Node(int _t=4, bool _leaf=false): t(_t), leaf(_leaf){
if(leaf) cNs=nullptr;
else{
cNs=new Node*[2*t];
}
key=new int[2*t-1];
}
~Node(){
if(!leaf){
delete[] this->cNs;
delete this->key;
}
}
void printKey(void){
for(int i=0; i<this->n; ++i){
std::cout<<key[i]<<' ';
}
std::cout<<std::endl;
}
};
struct BTree{
Node* root;
int t;
BTree(int _t): t(_t){}
void Create(void){
Node* x=new Node(this->t, true);
this->root=x;
}
Node* Search(Node* x, int k){
int i=0;
while(i<x->n && k>x->key[i]) i++;
if(i<x->n && k==x->key[i]) return x;
else if(x->leaf) return nullptr;
else{
return Search(x->cNs[i], k);
}
}
void SplitChild(Node* x, int i){
Node* y=x->cNs[i];
Node* z1=new Node(this->t, y->leaf);
Node* z2=new Node(this->t, y->leaf);
z1->n=this->t-1;
z2->n=this->t-1;
for(int j=0; j<this->t-1; ++j){
z1->key[j]=y->key[j];
z2->key[j]=y->key[j+this->t];
}
if(!(y->leaf)){
for(int j=0; j<this->t; ++j){
z1->cNs[j]=y->cNs[j];
z2->cNs[j]=y->cNs[j+this->t];
}
}
for(int j=x->n; j>=i+1; --j){
x->cNs[j+1]=x->cNs[j];
}
x->cNs[i]=z1;
x->cNs[i+1]=z2;
for(int j=x->n-1; j>=i; --j){
x->key[j+1]=x->key[j];
}
x->key[i]=y->key[this->t-1];
x->n++;
delete y;
}
void InsertNonFull(Node* x, int k){
int i=x->n-1;
if(x->leaf){
while(i>=0 && k<x->key[i]){
x->key[i+1]=x->key[i];
i--;
}
x->key[i+1]=k;
x->n++;
} else {
while(i>=0 && k<x->key[i]) i--;
i++;
if(x->cNs[i]->n==this->t*2-1){
SplitChild(x, i);
if(k>x->key[i]) i++;
}
InsertNonFull(x->cNs[i], k);
}
}
void Insert(int k){
Node* r=this->root;
if(r->n==this->t*2-1){
Node* s=new Node(this->t, false);
this->root=s;
s->cNs[0]=r;
SplitChild(s, 0);
InsertNonFull(s, k);
} else {
InsertNonFull(r, k);
}
}
};
int main(void){
BTree* btree=new BTree(2);
int alpha[]={4, 19, 17, 11, 3, 12, 8, 20, 22, 23, 13, 18, 14, 16, 1, 2, 24, 25, 4, 26, 5};
btree->Create();
for(int i=0; i<sizeof(alpha)/sizeof(int); ++i){
btree->Insert(alpha[i]);
Node* ret=btree->Search(btree->root, alpha[i]);
btree->root->printKey();
ret->printKey();
std::cout<<std::endl;
}
return 0;
}