B树(链表版)

声明

看书上的看不懂,就自己瞎想了一个。不知道还能不能叫做B树。它的本质是一串排好序的链表,然后根据B树的性质对顺序链表分层实现的。测试数据很少,不确定代码的正确性。

思路

  1. 插入一个数的时候进行链表的排序操作,并置这个数的层数为1(层数从下往上数
  2. 遍历顺序链表,检查是否存在相等的层数出现的次数之和(查询期间没有遇到高层的数)等于阶数,存在意味着溢出
  3. 溢出处理,将位于m/2(向上取整)位置的这个数的层数加一,加一后仍然溢出再重复此操作。

代码

创建

#include <stdio.h>

#include <stdlib.h>

#define N 3//阶数

typedef struct List{

    int data;

    int n;//从下往上层数

    struct List *next;

    struct List *child[N];

}List;//链表

typedef struct LList{

    List *front;

    List *root[N];//头指针

    int d;//最高层数

    int len;//总关键字

}BTList;//存放链表头指针和B树头指针

//初始化

int init_BTList(BTList *l){

    l->front=(List *)malloc(sizeof(List));

    if(!l->front) return 0;

    l->d=0;

    l->len=0;

    return 1;

}

//判断是否溢出

int find_Spilt(BTList *l,int d,int n){

   

    List *p,*q;  

    int t=0,flag;

    q=p=l->front;

    //向上取整

    if(N%2>0) flag=N/2+1;

    else flag=N/2;

    //溢出检查

    while (p->next){

        if(p->next->n==d){

            t=t+1;

            if(t==flag) q=p->next;

        }

        if(p->next->n>d) t=0;

        //溢出处理

        if(t==N){

                q->n=q->n+1;

                if(q->n > l->d) l->d=q->n;

                if(n) find_Spilt(l,q->n,n--);//处理后仍然溢出

               

                return 1;

        }

        p=p->next;    

    }    

    return 1;

}

//插入关键字

int insert_BTList(BTList *l,int a){

    if(l->len){

        List *p;

        p=l->front;

        //排序

        while (p->next)

        {

            if(p->next->data==a) return 1;

            else if(p->next->data<a){

                if(p->next->next) p=p->next;

                else{

                    List *q;

                    q=(List *)malloc(sizeof(List));

                    q->data=a;

                    q->n=1;

                    p->next->next=q;

                    q->next=NULL;

                    l->len++;

                    //溢出判断与处理

                    find_Spilt(l,1,l->d);

                    return 1;

                }

            }else{

                List *q;

                q=(List *)malloc(sizeof(List));

                q->data=a;

                q->n=1;

                q->next=p->next;

                p->next=q;

                l->len++;

                //溢出判断与处理

                find_Spilt(l,1,l->d);

                return 1;

            }

        }

    }else{

        l->front->next=(List *)malloc(sizeof(List));

        l->front->next->data=a;

        l->front->next->n=1;

        l->front->next->next=NULL;

        l->len++;

        return 1;

    }

}

//树的根节点

int root_BTList(BTList *l){

    List *p;int i=0;

    p=l->front;

    //根节点就是最高层数的数

    while (p->next)

    {

       if(p->next->n==l->d){

           

            l->root[i]=p->next;

            i++;

            l->len=i;

           

       }

       //输出树中的详情

       printf("值: %d 层数: %d ",p->next->data,p->next->n);

       printf("子值:");

       for(int i=0;i<N;i++){

            if(p->next->child[i]) printf(" %d ",p->next->child[i]->data);

       }

       printf("\n");

       p=p->next;

    }

   

}

//分配树的孩子节点

/*

n是孩子节点层数,m是父节点层数

遍历链表,记录阶数等于n的节点,然后第一次等于m的节点的孩子节点指向他们

*/

int child_BTList(BTList *l,int n,int m){

    if(n==N){

        return 1;

    }else{

        List *p,*q[N],*t;

        int flag=0,e=0,k=0;

        p=l->front;

        while (p->next)

        {

            if(p->next->n==n){

                q[flag]=p->next;

                flag++;

            }

            if(p->next->n>=m && e==1){

                for (int i = 0; i < flag; i++)

                {

                    t->child[i]=q[i];

                }

                flag=0;

                e=0;

                k=1;

            }

            if(p->next->n==m && e==0){

                t=p->next;

                e=1;

            }

            p=p->next;  

        }

        for (int i = 0; i < flag; i++)  

        {

            t->child[i]=q[i];

        }

        child_BTList(l,n+1,m+1);  

    }

}

//查找

int find_BTone(List *l[],int n){

    int k=0;

    if(l){

       

        for (int i = 0; i < N; i++)

        {

            if(l[i]){

                if(l[i]->data==n){//找到

                    printf("该值为:%d 所在层数为:%d",l[i]->data,l[i]->n);

                    return 1;

                }

                else{//未找到 去孩子那查找

                    if(l[i]->data<n) k=i;//对应孩子位置

                    else break;

                }

            }else{

                break;

            }

           

        }

        if(l[k]){//

            if(l[k]->child) find_BTone(l[k]->child,n);

        }

        else{

            printf("没找到");

            return 0;

        }

    }else{

        printf("没找到");

        return 0;

    }

}

 测试

int seach_BT(int a[],int n){

    BTList L;

    init_BTList(&L);

    for(int i=0;i<n;i++){

        insert_BTList(&L,a[i]);

    }

    child_BTList(&L,1,2);

    root_BTList(&L);

   

    printf("层数为:%d\n",L.d);

   //查找值为10的数

    find_BTone(L.root,10);

}

测试数据:5,8,7,1,3,2,6,10,4,9,20

 结果

  • 38
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值