【数据结构】算法9.13-9.14 B树-插入&查找

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW_SELF -2

#define EQ(a,b) ((a) == (b))
#define LT(a,b) ((a) <  (b))
#define LQ(a,b) ((a) <= (b))
#define M 3
typedef int Status;
typedef int ElemType;
typedef int KeyType;
typedef struct
{
    ElemType *elem; //unit elem[0] keep NULL
    int length;   //length of table
}SSTable;
typedef struct BTNode
{
    int keynum;   //结点中关键字个数,即结点的大小
    struct BTNode *parent;  //point to Parent node
    KeyType key[M+1];    //关键字向量,0号单元未用
    struct BTNode *ptr[M+1];  //子树指针向量
}BTNode,*BTree;
typedef struct
{
    BTNode *pt;  //指向找到的结点
    int i;   //1...M,在结点中的关键字序号
    int tag;  //1:found,0:unfound
}Result;  //B-Tree 的查找结果类型
/*******************************声明部分****************************************/
int Search(BTree p,KeyType K);
//在p->key[1...keynum]中查找,返回值i使得:p->key[i] <= K < p->key[i+1]
Result SearchBTree(BTree T,KeyType K);
//在M阶B树T上查找关键字K,返回结果(pt,i,tag),若查找成功,则特征值tag = 1,
//指针pt所指结点中第i个关键字等于K,否则特征值tag = 0,等于K的关键字应插入
//在指针pt所指结点中第i个和第i+1个关键字之间
Status insert(BTree q,int i,KeyType x,BTree ap);
//将x和ap分别插入到q->key[i+1]和q->ptr[i+1]
Status split(BTree q,int s,BTree *ap);
//将q->key[s+1...M],q->ptr[s...M]和q->recptr[s+1...M]移入新结点*ap
Status NewRoot(BTree *T,BTree q,KeyType x,BTree ap);
//生成含信息(T,x,ap)的新的根结点*T,原T和ap为子树指针
Status InsertBTree(BTree *T,KeyType K,BTree q,int i);
//在M阶B树T上结点*q的key[i]与key[i+1]之间插入关键字K,
//若引起结点过大,则沿双亲链进行必要的结点分裂调整,使T仍是M阶B树
Status CreateTalbe(SSTable *L);
Status InitTable(SSTable *L);

/*******************************函数部分****************************************/
int Search(BTree p,KeyType K)
{
    int i,j;
    for(i = 0,j = 1;j <= p->keynum;j++){
        if(p->key[j] <= K)
            i = j;
        else
            break;
    }
    return i;
}

Result SearchBTree(BTree T,KeyType K)
{
    BTree p,q;
    int found,i;

    p = T;  //初始化,p指向待查结点,q指向p的双亲
    q = NULL;
    found = FALSE;
    i = 0;

    while(p && !found){
        i = Search(p,K);
        if(i > 0 && p->key[i] == K)
            found = TRUE;  //找到关键字
        else{
            q = p;
            p = p->ptr[i];
        }
    }//while
    if(found){
        Result R1;
        R1.pt = p;
        R1.i = i;
        R1.tag = 1;
        return R1;
    }
    else{
        Result R0;
        R0.pt = q;
        R0.i = i;
        R0.tag = 0;
        return R0;
    }
}

Status Insert(BTree q,int i,KeyType x,BTree ap)
{
    int j;

    for(j = q->keynum;j > i;j--){   //所有元素后移
        q->key[j+1] = q->key[j];
        q->ptr[j+1] = q->ptr[j];
    }

    q->key[i+1] = x;
    q->ptr[i+1] = ap;
    q->keynum++;
    return OK;
}

Status split(BTree q,int s,BTree *ap)
{
    int i;

    (*ap) = (BTree)malloc(sizeof(BTNode));
    (*ap)->ptr[0] = q->ptr[s];

    for(i = s+1; i <= M;i++){
        (*ap)->key[i-s] = q->key[i];
        (*ap)->ptr[i-s] = q->ptr[i];
    }

    (*ap)->keynum = M - s;
    q->keynum = s-1;
    (*ap)->parent = q->parent;

    for(i = 0;i<=(*ap)->keynum;i++){
        if((*ap)->ptr[i])
            (*ap)->ptr[i]->parent = *ap;
    }
}

Status NewRoot(BTree *T,BTree q,KeyType x,BTree ap)
{
    BTree p;
    p = (BTree)malloc(sizeof(BTNode));
    p->keynum = 1;
    p->parent = NULL;
    p->key[1] = x;
    p->ptr[0] = *T;
    p->ptr[1] = ap;

    if(p->ptr[0])
        p->ptr[0]->parent = p;
    if(p->ptr[1])
        p->ptr[1]->parent = p;
    *T = p;
}

Status InsertBTree(BTree *T,KeyType K,BTree q,int i)
{
    KeyType x;
    BTree ap;
    int finished,s;

    x = K;
    ap = NULL;
    finished = FALSE;

    while(q && !finished){
        Insert(q,i,x,ap);
        if(q->keynum < M)
            finished = TRUE;  //Insert complete
        else{  //split the node *q
            s =ceil((double)M/2);
            split(q,s,&ap);
            x = q->key[s];
            q = q->parent;
            if(q)
                i = Search(q,x);
        }//else
    }//while
    if(!finished)
        NewRoot(T,q,x,ap);
    return OK;
}

Status CreateTalbe(SSTable *L)
{
  /*  int i;
    printf("请输入顺序表的长度:");
    scanf("%d",&L->length);
    for(i = 1;i<=L->length;i++){
        printf("请输入第 %d 个元素的值:",i);
        scanf("%d",&L->elem[i].key);
    }*/
    L->length = 15;
    L->elem[1] = 24;
    L->elem[2] = 45;
    L->elem[3] = 50;
    L->elem[4] = 53;
    L->elem[5] = 100;
    L->elem[6] = 37;
    L->elem[7] = 12;
    L->elem[8] = 61;
    L->elem[9] = 90;
    L->elem[10] = 70;
    L->elem[11] = 3;
    L->elem[12] = 30;
    L->elem[13] = 26;
    L->elem[14] = 85;
    L->elem[15] = 7;
    return OK;
}

Status InitTable(SSTable *L)
{
    (*L).elem = (ElemType *)malloc(100 * sizeof(ElemType));
    if(!(*L).elem)
        exit(OVERFLOW);
    (*L).length = 0;
    return OK;
}

Status CreateBTree(BTree *T,SSTable L)
{
    int i;
    *T = NULL;
    Result R;

    if(L.length){
        for(i = 1;i<=L.length;i++){
            R = SearchBTree(*T,L.elem[i]);
            if(!InsertBTree(T, L.elem[i], R.pt, R.i)){
                printf("插入失败!\n");
                break;
            }
        }
    }
    printf("插入完成\n");
    return OK;
}

void PrintBT_InOrder(BTree T)
{
    int j;
    if(T){
        for(j = 0;j<= T->keynum;j++){
            PrintBT_InOrder(T->ptr[j]);
            if(j < T->keynum)
                printf("%d ",T->key[j+1]);
        }
    }
}
/*******************************主函数部分**************************************/
int main()
{
    SSTable L;
    BTree T;

    printf("\n创建一个顺序表如下:\n");
    InitTable(&L);
    CreateTalbe(&L);

    int i;
    for(i = 1;i<= L.length;i++)
        printf("%d ",L.elem[i]);

    printf("\n\n创建一个B树,依次插入顺序表的元素\n");
    CreateBTree(&T,L);

    printf("\n中序遍历B树:\n");
    PrintBT_InOrder(T);

    printf("\n\n寻找是否存在元素 88 :\n");
    Result R;
    R = SearchBTree(T,88);
    printf("结果是:%d \n",R.tag);

    printf("\n将该元素 88 插入到B树中:\n");
    InsertBTree(&T, 88, R.pt, R.i);
    printf("插入完成\n");

    printf("\n再次中序遍历B树:\n");
    PrintBT_InOrder(T);
    printf("\n");

}



这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值