B树建立与遍历

 

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

# include "btrees.h"

/* 给一个结点分配空间 */
struct btnode * allocateNode(struct btnode *ptr){
    int i,max;
    ptr = (struct btnode *)malloc(sizeof(struct btnode));
    if(!ptr){
        printf("allocated error!\n");
        exit(1);
    }
    max = 2*M;
    for(i=0; i<max; i++)
        ptr->p[i] = NULL;   /* 初始化指针 */
    memset(ptr->k, 0, (max-1)*sizeof(int)); /* 初始化键的值*/
    return ptr;
}


/* 创建一个空的B树,就一个根结点 */
struct btnode * btreeCreate(struct btnode *root){
    root = allocateNode(root);
    root->keyNum = 0;
    root->isleaf = 1;
    return root;
}

/*函数目的:在B树中递归的搜索给定的数据,如果存在则返回数据所在节点和在节点中
 * 的位置,不存在返回NULL
 */
/*
struct searchResult * btreeSearch(struct btree *root, int data){
    int i=0;
    struct searchResult result;
    //找到节点中数据所在位置
    while((i<(2*M-1)) && (data>root->k[i]))
        i++;
    
    //数据找到,返回结果
    if(root->k[i] == data){
        result.ptr = root;
        result.pos = i;
        return result;
    }

    //已经搜索到叶节点,数据不存在,返回NULL
    if(root->isleaf){
        result.ptr = NULL;
        result.pos = -1;
        return result;
    }
    else{   //非叶节点,继续搜索子树节点
        return btreeSearch(root->p[i], data);
    }
}
*/

//函数目的:分裂存储数达到最大的节点
void btreeSplitChild(struct btnode *parent, int pos, struct btnode *child){
    struct btnode *child2;
    int i;
    //为新分裂出的节点分配空间
    child2 = allocateNode(child2);
    //与被分裂点同级
    child2->isleaf = child->isleaf;
    //设置节点数
    child2->keyNum = M-1;

    //复制数据
    for(i=0; i<M-1; i++)
        child2->k[i] = child->k[i+M];
    //如果不是叶节点,复制指针
    if(!child->isleaf)
        for(i=0; i<M; i++)
            child2->p[i] = child->p[i+M];
    child->keyNum = M-1;

    //将中间数作为索引插入到双亲节点中
    //插入点后面的关键字和指针都往后移动一个位置
    for(i=parent->keyNum; i>pos; i--){
        parent->k[i] = parent->k[i-1];
        parent->p[i+1] = parent->p[i];
    }
    parent->k[pos] = child->k[M-1];
    parent->keyNum++;
    parent->p[pos+1] = child2;
}

/* 函数目的:向非满的节点中插入一个数据
 * 注意:插入前保证key在原来的B树中不存在
 */
void btreeInsertNoneFull(struct btnode *ptr, int data){
    int i;
    struct btnode *child;   //要插入结点的子结点
    i = ptr->keyNum;
    //如果是叶节点,直接插入数据
    if(ptr->isleaf){
        while((i>0) && (data<ptr->k[i-1])){
            ptr->k[i] = ptr->k[i-1];
            i--;
        }
        //插入数据
        ptr->k[i] = data;
        ptr->keyNum++;
    }
    else{   //不是叶节点,找到数据应插入的子节点并插入
        while((i>0) && (data<ptr->k[i-1]))
            i--;
        child = ptr->p[i];
        if(child->keyNum == 2*M-1){
            btreeSplitChild(ptr, i, child);
            if(data > ptr->k[i])
                i++;
        }
        child = ptr->p[i];
        btreeInsertNoneFull(child, data);   //在子树中递归
    }
}


/* 插入一个结点 */
struct btnode * btreeInsert(struct btnode *root, int data){
    struct btnode *new;
    /* 检查是否根节点已满,如果已满,分裂并生成新的根节点 */
    if(root->keyNum == 2*M-1){
        new = allocateNode(new);
        new->isleaf = 0;
        new->keyNum = 0;
        new->p[0] = root;
        btreeSplitChild(new, 0, root);
        btreeInsertNoneFull(new, data);
        return new;
    }
    else{    //还没到最大数据数,直接插入
        btreeInsertNoneFull(root, data);
        return root;
    }
}

//函数目的:广度优先显示树
void btreeDisplay(struct btnode *root){
    int i, queueNum=0;
    int j;
    struct btnode *queue[20];
    struct btnode *current;

    //加入队列
    queue[queueNum] = root;
    queueNum++;

    while(queueNum>0){
        //出队
        current = queue[0];
        queueNum--;
        //移出第一个元素后后面的元素往前移动一个位置
        for(i=0; i<queueNum; i++)
            queue[i] = queue[i+1];
        //显示节点
        j = current->keyNum;
        printf("[ ");
        for(i=0; i<j; i++){
            printf("%d ", current->k[i]);
        }
        printf("]  ");

        //子节点入队
        if(current!=NULL && current->isleaf!=1){
            for(i=0; i<=(current->keyNum); i++){
                queue[queueNum] = current->p[i];
                queueNum++;
            }
        }
    }
    printf("\n");
}

int main()
{
    struct btnode *root;
    int a[13] = {18, 31, 12, 10, 15, 48, 45, 47, 50, 52, 23, 30, 20};
    int i;

    root = btreeCreate(root);
    for(i=0; i<13; i++){
        root = btreeInsert(root, a[i]);
        btreeDisplay(root);
    }

    return 0;
}

 

    原文作者:B树
    原文地址: https://blog.csdn.net/unix21/article/details/8600686
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞