c语言实现b树

概述:B 树(B-tree)是一种自平衡的搜索树数据结构,广泛应用于数据库和文件系统等领域。它的设计旨在提供一种高效的插入、删除和查找操作,同时保持树的平衡,确保各个节点的深度相差不大。

B 树的特点包括:

  1. 平衡性: 所有叶子节点到根节点的路径长度相等,确保在查找、插入和删除等操作时,各个节点的访问次数相对均衡,提高了性能。

  2. 多路搜索: B 树每个内部节点可以有多个子节点,这是与二叉搜索树的主要区别。每个节点包含多个关键字和对应的子树,这样可以减少树的高度,提高检索效率。

  3. 节点存储多个关键字: 每个节点可以存储多个关键字,而不仅仅是一个。这样可以提高每个节点的利用率,减少磁盘 I/O 次数。

  4. 自调整: 在插入和删除操作时,B 树会自动调整其结构以保持平衡。这通过节点分裂和合并的方式来实现。

B 树的阶数(order)是一个重要的概念,它表示一个节点最多可以包含的子节点数(或关键字数)。通常,B 树的阶数会根据具体的使用场景进行调整,以满足性能和空间的需求。

B 树广泛应用于数据库系统中,作为索引结构,因为它能够高效地支持范围查询、插入和删除操作。同时,B 树也被用于文件系统,以加速文件的检索和访问。

完整代码:

#include <stdio.h>
#include <stdlib.h>// B 树的阶数
#define ORDER 3// B 树节点结构
typedef struct BTreeNode {int leaf; // 是否是叶子节点int n;    // 当前关键字数量int keys[ORDER - 1]; // 关键字数组struct BTreeNode* child[ORDER]; // 子节点数组
} BTreeNode;// 创建新节点
BTreeNode* createNode() {BTreeNode* newNode = (BTreeNode*)malloc(sizeof(BTreeNode));newNode->leaf = 1;newNode->n = 0;for (int i = 0; i < ORDER - 1; ++i) {newNode->keys[i] = 0;}for (int i = 0; i < ORDER; ++i) {newNode->child[i] = NULL;}return newNode;
}// 分裂节点
void splitChild(BTreeNode* parent, int index, BTreeNode* child) {BTreeNode* newNode = createNode();newNode->leaf = child->leaf;newNode->n = ORDER / 2 - 1;// 将 child 中的一半关键字移动到 newNode 中for (int i = 0; i < ORDER / 2 - 1; ++i) {newNode->keys[i] = child->keys[i + ORDER / 2];}// 如果 child 不是叶子节点,将一半子节点移动到 newNode 中if (!child->leaf) {for (int i = 0; i < ORDER / 2; ++i) {newNode->child[i] = child->child[i + ORDER / 2];child->child[i + ORDER / 2] = NULL;}}// 调整 child 的关键字数量child->n = ORDER / 2 - 1;newNode->n = ORDER / 2 - 1;// 将 parent 中的一个关键字和 newNode 相关的子节点插入到 parent 中for (int i = parent->n; i > index; --i) {parent->keys[i] = parent->keys[i - 1];parent->child[i + 1] = parent->child[i];}parent->keys[index] = child->keys[ORDER / 2 - 1];parent->child[index + 1] = newNode;// 调整 parent 的关键字数量parent->n++;// 将 parent 中的一个关键字插入到 child 中child->keys[ORDER / 2 - 1] = 0;child->child[ORDER / 2] = NULL;
}// 插入非满节点
void insertNonFull(BTreeNode** root, int key) {BTreeNode* node = *root;int i = node->n - 1;// 如果是叶子节点,直接插入if (node->leaf) {while (i >= 0 && key < node->keys[i]) {node->keys[i + 1] = node->keys[i];i--;}node->keys[i + 1] = key;node->n++;} else {// 如果是内部节点,找到要插入的子节点while (i >= 0 && key < node->keys[i]) {i--;}i++;// 如果子节点已满,先分裂再插入if (node->child[i]->n == ORDER - 1) {splitChild(node, i, node->child[i]);if (key > node->keys[i]) {i++;}}// 递归插入子节点insertNonFull(&(node->child[i]), key);}
}// 插入关键字
void insert(BTreeNode** root, int key) {BTreeNode* node = *root;// 如果树为空,创建一个新节点作为根if (!node) {*root = createNode();(*root)->keys[0] = key;(*root)->n = 1;return;}// 如果根节点已满,先分裂再插入if (node->n == ORDER - 1) {BTreeNode* newRoot = createNode();newRoot->leaf = 0;newRoot->child[0] = *root;*root = newRoot;splitChild(newRoot, 0, node);insertNonFull(root, key);} else {insertNonFull(root, key);}
}// 打印 B 树
void printBTree(BTreeNode* node, int level) {if (node) {printf("Level %d: ", level);for (int i = 0; i < node->n; ++i) {printf("%d ", node->keys[i]);}printf("\n");if (!node->leaf) {for (int i = 0; i <= node->n; ++i) {printBTree(node->child[i], level + 1);}}}
}int main() {BTreeNode* root = NULL;// 插入一些关键字insert(&root, 3);insert(&root, 7);insert(&root, 2);insert(&root, 9);insert(&root, 1);insert(&root, 6);insert(&root, 4);insert(&root, 5);insert(&root, 8);// 打印 B 树printBTree(root, 0);return 0;
}

首先定义了B树的阶数ORDER为3,即每个节点最多可以有3个子节点。然后定义了一个B树节点的结构体,包含以下成员:

  • leaf:表示该节点是否为叶子节点,如果是叶子节点则为1,否则为0。
  • n:表示当前节点中关键字的数量。
  • keys:关键字数组,用于存储节点中的关键字。
  • child:子节点数组,用于存储指向子节点的指针。

接下来实现了创建新节点的函数createNode(),用于分配内存并初始化节点的成员变量。

然后实现了分裂节点的函数splitChild(),用于将一个节点分裂成两个节点。分裂过程包括将原节点的一半关键字移动到新节点中,并将原节点的一半子节点移动到新节点中。同时调整原节点的关键字数量和新节点的关键字数量。最后将原节点中的一个关键字和与新节点相关的子节点插入到原节点中,并调整原节点的关键字数量。

接着实现了插入非满节点的函数insertNonFull(),用于在非满节点中插入关键字。如果节点是叶子节点,则直接插入关键字;如果节点是内部节点,则找到要插入的子节点,如果子节点已满,则先分裂再插入。然后递归插入子节点。

最后实现了插入关键字的函数insert(),用于向B树中插入关键字。如果树为空,则创建一个新节点作为根;如果根节点已满,则先分裂再插入。然后调用insertNonFull()函数插入关键字。

最后实现了打印B树的函数printBTree(),用于按层次遍历的方式打印B树的结构。

在main()函数中,创建了一个空的根节点root,然后插入了一些关键字,并调用printBTree()函数打印B树的结构。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/622488.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

怎么使用好爬虫IP代理?爬虫代理IP有哪些使用技巧?

在互联网时代&#xff0c;爬虫技术被广泛应用于数据采集和处理。然而&#xff0c;在使用爬虫技术的过程中&#xff0c;经常会遇到IP被封禁的问题&#xff0c;这给数据采集工作带来了很大的困扰。因此&#xff0c;使用爬虫IP代理成为了解决这个问题的有效方法。本文将介绍如何使…

【redis基础1】基础数据类型详解和应用案例

博客计划 &#xff0c;我们从redis开始&#xff0c;主要是因为这一块内容的重要性不亚于数据库&#xff0c;但是很多人往往对redis的问题感到陌生&#xff0c;所以我们先来研究一下。 本篇&#xff0c;我们先看一下redis的基础数据类型详解和应用案例。 1.redis概述 以mysql为…

xtu oj 1340 wave

题目描述 一个n列的网格&#xff0c;从(0,0)网格点出发&#xff0c;波形存在平波(从(x,y)到(x1,y))&#xff0c;上升波(从(x,y)到(x1,y1))&#xff0c;下降波(从(x,y)到(x1,y−1))三种波形&#xff0c;请问从(0,0)出发&#xff0c;最终到达(n,0)的不同波形有多少种&#xff1f…

C++PythonC# 三语言OpenCV从零开发(1):环境配置

文章目录 前言课程选择环境配置PythonC#COpenCV官网下载新建C项目测试运行Csharp版Python版 gitee仓库总结 前言 由于老王我想转机器视觉方向的上位机行业&#xff0c;我就打算开始从零学OpenCV。但是目前OpenCV有两个官方语言&#xff0c;C和Pyhont。C# 有大佬做了对应的Open…

vue 自定义网页图标 favicon.ico 和 网页标题

效果预览 1. 添加配置 vue.config.js 在 module.exports { 内添加 // 自定义网页图标pwa: {iconPaths: {favicon32: "./favicon.ico",favicon16: "./favicon.ico",appleTouchIcon: "./favicon.ico",maskIcon: "./favicon.ico",msTil…

memory泄露分析方法(java篇)

#memory泄露主要分为java和native 2种&#xff0c;本文主要介绍java# 测试每天从monkey中筛选出内存超标的app&#xff0c;提单流转到我 首先&#xff0c;辨别内存泄露类型&#xff08;java&#xff0c;还是native&#xff09; 从采到的dumpsys_meminfo_pid看java heap&…

【ROS2】使用C++实现简单的发布订阅方

1 构建自定义数据类型 1、自定义消息类型Student 1.1 创建base_interfaces_demo包 1.2 创建Student.msg文件 string name int32 age float64 height 1.2 在cmakeLists.txt中增加如下语句 #增加自定义消息类型的依赖 find_package(rosidl_default_generators REQUIRED) # 为…

基于Java SSM框架实现学生成绩管理系统项目【项目源码+论文说明】

基于java的SSM框架实现学生成绩管理系统演示 摘要 学生成绩是高校人才培养计划的重要组成部分&#xff0c;是实现人才培养目标、培养学生科研能力与创新思维、检验学生综合素质与实践能力的重要手段与综合性实践教学环节。而学生所在学院多采用半手工管理学生成绩的方式&#…

FFmpeg技术详解

FFmpeg技术详解 本文概不介绍相关安装配置&#xff0c;详情请入官方或者其他大佬博客&#xff0c;此处做出推荐&#xff1a; https://ffmpeg.org/ FFmpeg官网 https://ffmpeg.github.net.cn/developer.html FFmpeg中文文档 https://blog.csdn.net/m0_47449768/article/details/…

steam搬砖项目赚钱吗?低门槛副业月入5k真的假的?

steam搬砖项目一开始默默无闻&#xff0c;现在越来越受欢迎&#xff0c;因为大家都看到了该项目的长期稳定性。 steam搬砖项目主要是搬csgo游戏装备和道具&#xff0c;从steam购买&#xff0c;在网易Buff上出售&#xff0c;赚取差价。只需少量投资&#xff0c;即可获得长期稳定…

软件测试|Python requests库的安装和使用指南

简介 requests库是Python中一款流行的HTTP请求库&#xff0c;用于简化HTTP请求的发送和处理&#xff0c;也是我们在使用Python做接口自动化测试时&#xff0c;最常用的第三方库。本文将介绍如何安装和使用requests库&#xff0c;以及一些常见的用例示例。 安装requests库 首…

Python Matplotlib 动画教程:提高可视化吸引力的强大工具【第24篇—python:Matplotlib】

文章目录 &#x1f356; 方法一&#xff1a;使用pause()函数&#x1f680; 方法二&#xff1a;使用FuncAnimation()函数&#x1f94b; 线性图动画&#xff1a;&#x1f3bb; Python中的条形图追赶动画&#x1f30c; Python中的散点图动画&#xff1a;&#x1f6f9; 条形图追赶的…

Java Web项目中 JSP 访问问题

一、名词说明&#xff1a; 1、JSP 文件一般有两个存放位置 &#xff08;1&#xff09;webapp 的 WEB-INF目录中 &#xff08;2&#xff09;webapp 目录中 其中 存放在 WEB-INF 被成为 安全目录 安全目录&#xff1a;就是客户端无法访问&#xff0c;只有服务端可以访问的…

day01

文章目录 创建Vue实例插值表达式响应式数据常见标签v-htmlv-show v-ifv-if v-else-if v-elsev-onv-bindv-forv-model 综合案例 创建Vue实例 <!--创建Vue实例&#xff0c;初始化渲染1. 准备容器2. 引包&#xff08;官网&#xff09; — 开发版本/生产版本3. 创建Vue实例 ne…

Maven《一》-- 一文带你快速了解Maven

目录 &#x1f436;1.1 为什么使用Maven 1. Mavan是一个依赖管理工具 ①jar包的规模 ②jar包的来源问题 ③jar包的导入问题 ④jar包之间的依赖 2. Mavan是一个构建工具 ①你没有注意过的构建 ②脱离IDE环境仍需构建 3. 结论 &#x1f436;1.2 什么是Maven &#x…

感知机(二分类模型)

目录 1.感知机计算预测值&#xff1a;2.感知机训练&#xff1a;3.损失函数&#xff1a;4.多层感知机&#xff1a;5.单隐藏层的多层感知机代码实现&#xff1a; 1.感知机计算预测值&#xff1a; 训练结果只有1、-1&#xff0c;故正负相同训练正确&#xff0c;正负相反即训练错误…

【DB】MySQL版本5.7和8的区别,以及升级的注意事项

文章目录 1、MySQL版本5.7和8的区别2、MySQL 5.7升级8 1、MySQL版本5.7和8的区别 在数据库管理系统中&#xff0c;MySQL是一个广泛使用、开源的解决方案。它提供了强大的功能&#xff0c;同时具有优秀的性能和可扩展性。 MySQL 5的发布于2005年&#xff0c;在MySQL数据库的发…

实体企业品牌推广之困与解:迅腾文化如何助力企业“显”化品牌价值

在数字化浪潮的冲击下&#xff0c;许多实体企业面临着品牌推广的困境。由于缺乏系统的经验和网络资源的积累&#xff0c;这些企业在品牌推广过程中有很大提升空间。如何以低成本的方式有效推广品牌&#xff0c;成为了实体企业亟待解决的问题。迅腾文化从策略到设计&#xff0c;…

Linux第26步_在虚拟机中安装stm32wrapper4dbg工具

在Ubuntu下编译TF-A 或者 Uboot时&#xff0c;我们需要用到ST公司提供的stm32wrapper4dbg工具。stm32wrapper4dbg工具的源码下载地址为: GitHub - STMicroelectronics/stm32wrapper4dbg 记得我们在前面已经创建过的目录如下&#xff1a; 1&#xff09;、在根目录下&#xf…

Windows项目部署流程

一、部署前需要的工作 ①配置环境变量&#xff1a;将所需的软件和工具的安装路径添加到系统的环境变量中&#xff0c;以便在命令行中可以直接使用。 ②部署项目文件&#xff1a;将项目的文件和代码复制到服务器上的指定目录中&#xff0c;例如Web服务器的网站根目录。 ③配置…