cjb中的cjb的数据结构
相当于平衡二叉树的扩展版,一个节点的分叉数[t-1,2t-1),通过多分叉限定了搜索范围区间,相当于每个节点对数据范围分块,区域块与区域块间秉承树结构的搜索树,美称“多路归并搜索树”。
发明这种算法是因为硬盘的磁头移动速度非常慢,所以锁定了一段磁道尽量多读取一段范围的数据,通过B树这种慢但存储范围巨大的数据结构存储磁盘读出的内容,这样以后再次访问磁盘这段空间可以在B树上查找(根据空间局部性原理,这块磁盘内容很可能再次用到)。。相当于牺牲时间换空间的平衡树,所以基本只应用在文件索引、磁盘访问、数据库上这种存储按块(页)、各种原因需一次读取相当多数据的情况,在算法竞赛上可谓是毫无卵用了。。

插入删除查找复杂度均为图片说明 ,隶属平衡树家族,当节点上下界因子t取2时就进化成了平衡二叉树。

插入卫星数据要分裂满节点,删除卫星数据要合并节点,编写难度在平衡树家族中位于中等偏上级别,个人感觉实现上略难于红黑树。

删除操作性质维护操作:
1、如果关键字k在节点x中,且x为叶节点,则从x中删除k
2、如果k在节点x中,且x为内部节点,则做以下操作:
a.节点x前于k的子节点y至少包含t个关键字,则找出k在以y为根的子树的前驱k',递归删除k',并在x中用k'代替k
b.如果y有少于k个关键字,则检查节点x中后于k的子节点z,如果z至少包含t个关键字,则找出k在以z为根的子树中的后继k',递归删除k',并在x中用k'代替k。
c.否则如果y和z都只含有t-1个关键字,则将k和z的全部合并至y,这样x失去了k和指向z的指针,并且y现在包含2t-1个关键字,然后释放z并递归地从y中删除k。
3、如果关键字k不在内部节点x中,则确定必包含k的子树的根x.ci(如果k确实在树中)。如果x.ci只有t-1个关键字,则执行3a或3b来保证降至一个至少包含t个关键字的节点。
a.如果x.ci只含有t-1个关键字,但其相邻兄弟至少含有t个关键字,则将x中的某一个关键字降至x.ci中,将x.ci的相邻左或右兄弟的一个关键字升至x,将该兄弟中的相应孩子指针移到x.ci中,这样使得x.ci增加了一个额外的关键字。
b.如果x.ci及x.ci的所有相邻兄弟只包含t-1个关键字,则将x.ci与一个兄弟合并,即将x的一个关键字移至新合并的节点,使其成为该节点的中间关键字。

#include<stdio.h>
const int N1=10;
const int N=1e5+5;
struct node
{
    int size;
    long long num[N1];
    int net[N1+2];
    short leaf;
}B[N+5];
int qos=1;//目前分配节点到的位置,线性分配 
int t=4;
int root;
struct pos
{
    int node_id;
    int pos_id;
    pos(int a=0,int b=0)
    {
        this->node_id=a;
        this->pos_id=b;
    };
};

inline void disk_read(int x,int arr)
{}
inline void disk_write(int x)
{}
inline void free(int x)
{}

pos b_search(int x,int k)
{
    int i=1;
    while(i<=B[x].size&&k>B[x].num[i])
    i++;
    if(i<=B[x].size&&k==B[x].num[i])
    {
        return pos(x,i);
    }
    else if(B[x].leaf)
    return pos(-1,-1);
    else {
        disk_read(x,B[x].net[i]);
        return b_search(B[x].net[i],k);
    }
}

void b_create()
{
    B[1].leaf=1;
    B[1].size=0;
    root=1;
    disk_write(1);
}

void b_split(int x,int i)//B树分裂 
{
    int z=++qos;
    int y=B[x].net[i];
    B[z].leaf=B[y].leaf;
    B[z].size=t-1;
    for(int j=1;j<=t-1;j++)//1 2 3-4-5 6 7
        B[z].num[j]=B[y].num[t+j];
    if(!B[y].leaf)
        for(int j=1;j<=t;j++)
            B[z].net[j]=B[y].net[t+j];
    B[y].size=t-1;
    for(int j=B[x].size+1;j>=i+1;j--)
    B[x].net[j+1]=B[x].net[j];
    B[x].net[i+1]=z;
    for(int j=B[x].size;j>=i;j--)
    B[x].num[j+1]=B[x].num[j];
    B[x].num[i]=B[y].num[t];
    B[x].size++;
    disk_write(y);
    disk_write(z);
    disk_write(x);
}

void b_insert_nonfull(int x,int k)//insert辅助过程 将关键字插入节点x,要求调用时x是非满的 
{
    int i=B[x].size;
    if(B[x].leaf)
    {
        while(i>=1&&k<B[x].num[i])
        {
            B[x].num[i+1]=B[x].num[i];
            i--;
        }
        B[x].num[i+1]=k;
        B[x].size++;
        disk_write(x);
    }
    else {
        while(i>=1&&k<B[x].num[i])
        i--;
        i++;
        disk_read(x,i);
        if(B[B[x].net[i]].size==2*t-1)
        {
            b_split(x,i);
            if(k>B[x].num[i])//合并提上来了一个分割点,和这个提上来的比较来确定插入位置 
            i++;
        } 
        b_insert_nonfull(B[x].net[i],k);
    } 
}

void b_insert(int k)//插入处理根节点 
{
    int r=root;
    if(B[r].size==2*t-1)
    {
        int s=++qos;
        root=s;
        B[s].leaf=B[s].size=0;
        B[s].net[1]=r;
        b_split(s,1);
        b_insert_nonfull(s,k);
    }
    else b_insert_nonfull(r,k);
}

void b_merge(int x,int i,int y,int z)//b树合并
{
    B[y].size=2*t-1;
    for(int j=t+1;j<=2*t-1;j++)
        B[y].num[j]=B[z].num[j-t];
    B[y].num[t]=B[x].num[i];
    if(!B[y].leaf)
    for(int j=t+1;j<=2*t-1;j++)
    B[y].net[j]=B[z].net[j-t];
    for(int j=i+1;j<=B[x].size;j++)
    B[x].net[j]=B[x].net[j+1];
    B[x].size--;
    free(z);
    disk_write(x),disk_write(z),disk_write(y);
}

long long b_pre(int x)
{
    int i=B[x].size;
    while(!B[x].leaf)
    {
        disk_read(x,i+1);
        x=B[x].net[i+1];
        i=B[x].size;
    }
    return B[x].num[i];
}

long long b_suc(int x)
{
    while(!B[x].leaf)
    {
        disk_read(x,1);
        x=B[x].net[1];
    }
    return B[x].num[1];
}

void b_shift_right(int x,int i,int y,int z)
{
    B[z].size++;
    int j=B[z].size;
    while(j>1)
    {
        B[z].num[j]=B[z].num[j-1];
        j--;
    }
    B[z].num[1]=B[x].num[i];
    B[x].num[i]=B[y].num[B[y].size];
    if(!B[z].leaf)
    {
        j=B[z].size;
        while(j)
        {
            B[z].net[j+1]=B[z].net[j];
            j--;
        }
        B[z].net[1]=B[y].net[B[y].size+1];
    }
    B[y].size--;
    disk_write(x),disk_write(y),disk_write(z);
}

void b_shift_left(int x,int i,int y,int z)
{
    B[y].size++;
    B[y].num[B[y].size]=B[x].num[i];
    B[x].num[i]=B[z].num[1];
    B[z].size--;
    int j=1;
    while(j<=B[z].size)
    {
        B[z].num[j]=B[z].num[j+1];
        j++;
    }
    if(!B[z].leaf)
    {
        B[y].net[B[y].size+1]=B[z].net[1];
        j=1;
        while(j<=B[z].size+1)
        {
            B[z].net[j]=B[z].net[j+1];
            j++;
        }
    }
    disk_write(x),disk_write(y),disk_write(z);
}

int fl;//是否删除失败 
void b_delete_nonnull(int x,int k)
{
    int i=1;
    if(B[x].leaf)//1
    {
        while(i<=B[x].size&&k>B[x].num[i])
        i++;
        if(k==B[x].num[i])
        {
            for(int j=i+1;j<=B[x].size;j++)
            B[x].num[j-1]=B[x].num[j];
            B[x].size--;
            disk_write(x);
        }
        else {
            fl=1;
        }
    }
    else {
        while(i<=B[x].size&&k>B[x].num[i])
        i++; 
        disk_read(x,i);
        int y=B[x].net[i];
        int z=0;
        if(i<=B[x].size)
        {
            disk_read(x,i+1);
            z=B[x].net[i+1];
        }
        if(k==B[x].num[i])//2
        {
            if(B[y].size>t-1)//2a
            {
                long long k1=b_pre(y);
                b_delete_nonnull(y,k1);
                B[x].num[i]=k1;
            }
            else if(B[z].size>t-1)//2b
            {
                long long k1=b_suc(z);
                b_delete_nonnull(z,k1);
                B[x].num[i]=k1;
            }
            else {//2c
                b_merge(x,i,y,z);
                b_delete_nonnull(y,k);
            }
        }
        else {//3
            int p=0;
            if(i>1)
            {
                disk_read(x,i-1);
                p=B[x].net[i-1]; 
            }
            if(B[y].size==t-1)
            {
                if(i>1&&B[p].size>t-1)//3a
                    b_shift_right(x,i,p,y);
                else if(i<=B[x].size&&B[z].size>t-1)//3a
                    b_shift_left(x,i,y,z);
                else if(i>1)//3b
                {
                    b_merge(x,i,p,y);
                    y=p;
                }
                else b_merge(x,i,y,z); 
            }
            b_delete_nonnull(y,k);
        }    
    }
}

void b_delete(int k)
{
    int r=root;
    if(B[r].size==1)
    {
        disk_read(r,1),disk_read(r,2);
        int y=B[r].net[1];
        int z=B[r].net[2];
        if(B[y].size==B[z].size==t-1)//2c or 3b
        {
            b_merge(r,1,y,z);
            free(r);
            b_delete_nonnull(y,k);
        }
        else b_delete_nonnull(r,k);
    }
    else b_delete_nonnull(r,k);
} 

int main()
{

} 
/*
测试程序
    b_create();
    for(int i=1;i<10;i++)
    b_insert(i*2+1);
    for(int i=1;i<=30;i++)
    {
        pos t=b_search(root,i);
        printf("%d %d %d\n",i,t.node_id,t.pos_id);
    }
    b_delete(3);
    b_delete(7);
    for(int i=1;i<=30;i++)
    {
        pos t=b_search(root,i);
        printf("%d %d %d\n",i,t.node_id,t.pos_id);
    }
*/