B树代码实现

本文详细介绍了B树的数据结构及其关键操作,包括创建结点、初始化、查找、插入(处理关键字插入和结点分裂修复)、以及打印节点信息。通过测试代码展示了如何在五阶B树中执行这些操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

插入数据

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

//B树结点
typedef struct BTNode {
    int *key;//关键字数组
    int num;//结点关键字个数
    struct BTNode *parent;//双亲结点
    struct BTNode **child;//孩子结点数组
} BTNode;

//B树
typedef struct BT {
    int order;//阶数
    BTNode *root;//根结点
} BT;

//创建结点
BTNode *createBTNode(int order) {
    BTNode *pNode = (BTNode *) malloc(sizeof(BTNode));//分配空间
    pNode->key = (int *) malloc(sizeof(int) * order);//多一位方便后续使用
    pNode->num = 0;//结点关键字个数默认为0
    pNode->parent = NULL;//结点双亲默认为空
    pNode->child = (BTNode **) malloc(sizeof(BTNode *) * (order + 1));//多一位方便后续使用
    for (int i = 0; i < order; ++i) {
        pNode->key[i] = 0;//关键字全部默认为0
    }
    for (int i = 0; i < order + 1; ++i) {
        pNode->child[i] = NULL;//每个孩子默认为空
    }
    return pNode;//返回新结点
}

//初始化
void initBT(BT *bt, int order) {
    bt->order = order;//设置B树阶数
    bt->root = createBTNode(order);//创建根结点
}

//查找关键字
bool searchBT(BT *bt, int key, BTNode **pNode, int *index) {
    BTNode *p = *pNode = bt->root;//记录查找关键字所在结点
    int i = *index = 0;//记录查找关键字所在下标
    while (p) {
        *pNode = p;//更新地址
        *index = i;//更新下标
        if (p->num == i || p->key[i] > key) {
            p = p->child[i];//向孩子继续寻找关键字
            i = 0;//下标重置为0
        } else if (p->key[i] < key) {
            i++;//向下一个下标寻找关键字
        } else {
            return true;//找到关键字
        }
    }
    return false;//没有找到关键字
}

//分裂结点
BTNode *splitNode(BT *bt, BTNode *pNode1) {
    BTNode *pNode2 = createBTNode(bt->order);//创建一个新节点存放原来结点的后半段
    for (int i = 0; i < bt->order / 2; ++i) {
        pNode2->key[i] = pNode1->key[1 + i + bt->order / 2];
    }
    for (int i = 0; i < 1 + bt->order / 2; ++i) {
        pNode2->child[i] = pNode1->child[1 + i + bt->order / 2];
        if (pNode2->child[i]) {
            pNode2->child[i]->parent = pNode2;
        }
    }
    pNode2->num = pNode1->num = bt->order / 2;
    pNode2->parent = pNode1->parent;
    return pNode2;
}

//插入修复
void insertFix(BT *bt, BTNode *pNode1) {
    BTNode *pNode2 = splitNode(bt, pNode1);
    if (pNode1->parent) {
        int i = 0;//记录向上的结点应该去的位置
        while (i != pNode1->parent->num && pNode1->key[bt->order / 2] > pNode1->parent->key[i]) {
            i++;
        }
        for (int j = pNode1->parent->num; j > i; j--) {
            pNode1->parent->key[j] = pNode1->parent->key[j - 1];
            pNode1->parent->child[j + 1] = pNode1->parent->child[j];
        }
        pNode1->parent->key[i] = pNode1->key[bt->order / 2];
        pNode1->parent->child[i + 1] = pNode2;
        pNode1->parent->num++;
        if (pNode1->parent->num == bt->order) {
            insertFix(bt, pNode1->parent);
        }
    } else {
        initBT(bt, bt->order);//从新创建一个根结点
        bt->root->key[0] = pNode1->key[bt->order / 2];
        bt->root->child[0] = pNode1;
        bt->root->child[1] = pNode2;
        bt->root->num++;
        pNode1->parent = pNode2->parent = bt->root;//设置双亲
    }
}

//插入
void insertBT(BT *bt, int key) {
    BTNode *p = NULL;//记录关键字插入的结点
    int i = 0;
    if (searchBT(bt, key, &p, &i)) {
        printf("关键字已存在!\n");
        return;//关键字存在不进行插入操作
    }
    for (int j = p->num; j > i; j--) {
        p->key[j] = p->key[j - 1];//把比插入关键字大的关键字往后移动一格
    }
    p->key[i] = key;
    p->num++;//插入关键字后个数增加
    if (p->num == bt->order) {
        insertFix(bt, p);//如果关键字超出个数则开始调整
    }
}

//打印信息
void printBT(BT *bt) {
    BTNode *queue[1024] = {NULL};//创建一个简单的队列
    int front = 0, rear = 0;//记录头和尾
    queue[rear++] = bt->root;//根结点入队
    rear++;//每入队一层就留一个空结点方便判断
    while (front != rear - 1) {
        if (queue[front]) {
            printf("{");
            for (int i = 0; i < queue[front]->num; ++i) {
                if (i > 0) {
                    printf(",");//关键字用逗号隔开
                }
                printf("%d", queue[front]->key[i]);
            }
            printf("} ");
            for (int i = 0; i < queue[front]->num + 1; ++i) {
                if (queue[front]->child[i]) {
                    queue[rear++] = queue[front]->child[i];//孩子入队
                }
            }
        } else {
            printf("\n");//进入下一层换行
            rear++;//留下空结点
        }
        front++;
    }
    printf("\n");
}

//测试代码
void test() {
    BT bt;
    initBT(&bt, 5);//创建一个五阶B树
    int sel, key;
    while (true) {
        printf("1.插入数据\n2.删除数据\n3.打印信息\n");
        scanf("%d", &sel);
        switch (sel) {
            case 1: {
                printf("关键字:");
                scanf("%d", &key);
                insertBT(&bt, key);
                break;
            }
            case 2: {
                printf("关键字:");
                scanf("%d", &key);
                break;
            }
            case 3: {
                printBT(&bt);
                break;
            }
            default:
                return;
        }
        system("pause");
        system("cls");
    }
}

//主函数
int main() {
    test();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

花园宝宝没有天线

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值