#include<stdio.h>
#include<stdlib.h>
#define M 3
//2-3b树的实现 3阶b树
typedef struct btree{
int count;//结点中元素个数 即关键字个数
int element[M-1];
struct btree* next[M];
bool isLeaf;//增加一个是否是叶子结点判断
}*Btree;
//打印
void print(Btree B){
for(int i=0;i<B->count;i++){
printf("%d ",B->element[i]);
}
printf("\n");
for(int i=0;i<B->count+1;i++){
if(B->next[i]!=NULL){
print(B->next[i]);
}
}
}
//插入
Btree insert(int X,Btree Root,Btree B){
if(B==NULL){
//B为空
B=(Btree)malloc(sizeof(struct btree));
B->element[0]=X;
B->count=1;
for(int i=0;i<B->count+1;i++){
B->next[i]=NULL;
}
B->isLeaf=true;
//print(Root);
return B;
}else{
//b不为空
// 递归找出X的位置 然后回溯
Btree P=NULL;
for(int i=0;i<B->count;i++){
if(X<B->element[0]){
//在最左边
P=insert(X,Root,B->next[0]);
break;
}else if(X>B->element[i]&&i+1<B->count&&X<=B->element[i+1]){
//在i与i+1之间那个指针
P=insert(X,Root,B->next[i+1]);
break;
}else if(X>B->element[B->count-1]){
//在最右边
P=insert(X,Root,B->next[B->count]);
break;
}
}
//开始回溯判断是否需要向上移
if(P!=NULL&&B->count<(M-1)){
//可以直接插入
for(int i=0;i<B->count;i++){
int flag=-1;
//判断位置
if(P->element[P->count-1]<B->element[0]){
flag=0;
}else if(P->element[P->count-1]>B->element[i]&&i+1<B->count&&X<B->element[i+1]){
flag=i+1;
}else if(P->element[P->count-1]>B->element[B->count-1]){
flag=B->count;
}
if(flag!=-1){
for(int j=B->count;j>flag;j--){
B->element[j]=B->element[j-1];
}
B->element[flag]=P->element[P->count-1];
B->count++;
P->count--;
if(!P->isLeaf){
//如果不是叶子 必须加一个指针去指向它
for(int j=B->count;j>flag+1;j--){
B->next[j]=B->next[j-1];
}
B->next[flag+1]=P;
}else{
//叶子 加入一个空指针
B->next[B->count]=NULL;
}
break;
}
}
//print(Root);
if(B==Root){
//如果是根,返回根
return Root;
}else{
return NULL;
}
}else if(P!=NULL&&B->count==(M-1)){
//已经满了 必须进行分裂
//分两种情况
//1.B为根结点
Btree Q=(Btree)malloc(sizeof(struct btree));
Q->count=0;
Q->isLeaf=false;
//非根结点
//将该结点分成两个结点,找出中间的数据
//先将中间元素替换出来
// if(P->element[count-1]==B->element[B->count/2]);
int temp=-1;
for(int i=0;i<B->count;i++){
if(P->element[P->count-1]<=B->element[i]){
//他的新位置就是 i
//判断i是不是中间位置
if(i==B->count/2){
//刚好为中间结点,直接返回去这个数值
temp=P->element[P->count-1];
}else if(i<B->count/2){
//i在左部
temp=B->element[B->count/2-1];
for(int j=B->count/2-1;j>i;j--){
B->element[j]=B->element[j-1];
}
B->element[i]=P->element[P->count-1];
}else if(i>B->count/2){
//i在右部
temp=B->element[B->count/2];
for(int j=B->count/2;j<i;j++){
B->element[j]=B->element[j+1];
}
B->element[i]=P->element[P->count-1];
}
break;
}else if(P->element[P->count-1]>B->element[B->count-1]){
//大于最大的 在最右边
temp=B->element[B->count/2];
for(int j=B->count/2;j<B->count-1;j++){
B->element[j]=B->element[j+1];
}
B->element[B->count-1]=P->element[P->count-1];
break;
}
}
P->count--;
//新增的右部结点
for(int j=B->count/2;j<B->count;j++){
//将B结点的右部全部复制到Q中
Q->element[Q->count++]=B->element[j];
}
if(!P->isLeaf){
//非叶子结点,复制指针
Q->next[0]=P;
for(int i=1;i<Q->count+1;i++){
Q->next[i]=B->next[B->count/2+i];
}
}else{
//叶子结点,所有指针为空
for(int i=0;i<Q->count+1;i++){
Q->next[i]=NULL;
}
}
// Q->next[Q->count]=B->next[B->count];
//将该数值放在Q末尾
Q->element[Q->count++]=temp;
//b的数目减少一半
B->count-=B->count/2;
if(B==Root){
//为根时 必须形成新根
Btree newRoot=(Btree)malloc(sizeof(struct btree));
newRoot->element[0]= Q->element[Q->count-1];
newRoot->count=1;
Q->count--;
newRoot->next[0]=B;
newRoot->next[1]=Q;
newRoot->isLeaf=false;
return newRoot;
}
return Q;
}
if(B==Root){
return B;
}else{
return NULL;
}
}
}
int main(){
Btree B=NULL;
B=insert(22,B,B);
printf("插入22:\n");
print(B);
B=insert(16,B,B);
printf("插入16:\n");
print(B);
B=insert(41,B,B);
printf("插入41\n");
print(B);
B=insert(58,B,B);
printf("插入58\n");
print(B);
B=insert(8,B,B);
printf("插入8\n");
print(B);
B=insert(11,B,B);
printf("插入11\n");
print(B);
B=insert(12,B,B);
printf("插入12\n");
print(B);
B=insert(16,B,B);
printf("插入16\n");
print(B);
B=insert(17,B,B);
printf("插入17\n");
print(B);
B=insert(22,B,B);
printf("插入22\n");
print(B);
B=insert(23,B,B);
printf("插入23\n");
print(B);
B=insert(31,B,B);
printf("插入31\n");
print(B);
B=insert(41,B,B);
printf("插入41\n");
print(B);
B=insert(52,B,B);
printf("插入52\n");
print(B);
B=insert(58,B,B);
printf("插入58\n");
print(B);
B=insert(59,B,B);
printf("插入59\n");
print(B);
B=insert(61,B,B);
printf("插入61\n");
print(B);
}