B树的简单实现

template<class K, size_t M>
struct BTreeNode
{K _keys[M]; // 用于存储关键字的数组,最多容纳 M 个关键字(超额一个,为分裂提供空间)。BTreeNode<K, M>* _subs[M + 1]; // 存储子节点的指针数组,最多 M+1 个子节点。BTreeNode<K, M>* _parent; // 指向父节点的指针。size_t _n; // 当前节点中实际存储的关键字数量。// 构造函数,初始化节点的各个属性。BTreeNode(){for (size_t i = 0; i < M; i++){_keys[i] = K(); // 初始化关键字数组为默认值。_subs[i] = nullptr; // 初始化子节点指针为空。}_subs[M] = nullptr; // 多余的子节点指针初始化为空。_parent = nullptr; // 父节点初始化为空。_n = 0; // 初始关键字数量为 0。}
};
  • 作用:定义 B 树节点的结构,包括关键字数组、子节点指针、父节点指针和当前节点的关键字数量。
  • 意义
    • 为 B 树的基本操作(插入、删除、查找等)提供节点存储结构。
    • 允许节点存储最多 M 个关键字和 M+1 个子节点。

template<class K, size_t M>
class BTree
{typedef BTreeNode<K, M> Node; // 定义一个别名,便于后续引用节点类型。public:pair<Node*, int> Find(const K& key)
{Node* cur = _root; // 从根节点开始查找。Node* parent = nullptr; // 记录当前节点的父节点。while (cur){size_t i = 0;// 在当前节点中逐一比较关键字while (i < cur->_n){if (key < cur->_keys[i]) // 如果目标关键字小于当前关键字,停止查找。{break;}else if (key > cur->_keys[i]) // 如果目标关键字大于当前关键字,继续查找。{i++;}else // 找到目标关键字,返回节点和索引。{return make_pair(cur, i);}}parent = cur; // 更新父节点为当前节点。cur = cur->_subs[i]; // 进入对应的子节点。}return make_pair(parent, -1); // 未找到,返回最近的父节点及无效索引。
}void InsertKey(Node* node, const K& key, Node* child)
{int end = node->_n - 1; // 从节点的最后一个关键字开始比较。while (end >= 0){if (key < node->_keys[end]) // 如果新关键字小于当前关键字,向右移动当前关键字和其右子树。{node->_keys[end + 1] = node->_keys[end];node->_subs[end + 2] = node->_subs[end + 1];end--;}else // 如果新关键字大于等于当前关键字,停止移动。{break;}}node->_keys[end + 1] = key; // 插入新关键字。node->_subs[end + 2] = child; // 插入对应的子节点。if (child){child->_parent = node; // 更新子节点的父节点指针。}node->_n++; // 更新节点的关键字数量。
}bool Insert(const K& key)
{if (_root == nullptr) // 如果树为空,创建根节点并插入关键字。{_root = new Node;_root->_keys[0] = key;_root->_n++;return true;}// key已经存在,不允许插入pair<Node*, int> ret = Find(key);if (ret.second >= 0){return false;}K newKey = key; // 保存当前要插入的关键字。Node* child = nullptr; // 保存分裂后产生的新节点。Node* parent = ret.first; // 从查找到的父节点开始插入。while (1){InsertKey(parent, newKey, child); // 插入关键字到节点。if (parent->_n < M) // 如果节点未满,插入完成。{return true;}else // 如果节点满了,进行分裂。{size_t mid = M / 2; // 找到中间关键字的位置。Node* brother = new Node; // 创建一个新节点作为兄弟节点。size_t j = 0;size_t i = mid + 1;for (; i <= M - 1; i++) // 将中间关键字右边的部分移动到兄弟节点。{brother->_keys[j] = parent->_keys[i];brother->_subs[j] = parent->_subs[i];if (parent->_subs[i]){parent->_subs[i]->_parent = brother;}j++;}brother->_subs[j] = parent->_subs[i]; // 拷贝最后一个右子树。if (parent->_subs[i]){parent->_subs[i]->_parent = brother;}brother->_n = j; // 更新兄弟节点的关键字数量。parent->_n -= (brother->_n + 1); // 更新父节点的关键字数量。K midkey = parent->_keys[mid]; // 提取中间关键字。parent->_keys[mid] = K(); // 清空中间关键字。if (parent->_parent == nullptr) // 如果分裂的是根节点,创建新根节点。{_root = new Node;_root->_keys[0] = midkey;_root->_subs[0] = parent;_root->_subs[1] = brother;_root->_n = 1;parent->_parent = _root;brother->_parent = _root;break;}else // 如果分裂的不是根节点,继续向上插入。{newKey = midkey;child = brother;parent = parent->_parent;}}}return true;
}void _Inorder(Node* root)
{if (root == nullptr){return;}size_t i = 0;for (i = 0; i < root->_n; i++) // 遍历当前节点的关键字和子树。{_Inorder(root->_subs[i]); // 递归遍历左子树。cout << root->_keys[i] << " "; // 打印当前关键字。}_Inorder(root->_subs[i]); // 遍历最后一个右子树。
}

 

void TestBtree()
{int a[] = {53, 139, 75, 49, 145, 36, 101}; // 要插入的关键字数组。BTree<int, 3> t; // 创建阶数为 3 的 B 树。for (auto e : a){t.Insert(e); // 插入每个关键字。}t.Inorder(); // 打印中序遍历结果。
}

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

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

相关文章

2020 年 9 月青少年软编等考 C 语言三级真题解析

目录 T1. 因子问题思路分析T2. 质数的和与积思路分析T3. 括号匹配问题思路分析T4. 吃糖果 2思路分析T5. 铺砖思路分析T1. 因子问题 任给两个正整数 n n n、 m m m,求一个最小的正整数 a a a,使得 a a a 和 ( m − a ) (m-a) (m−a) 都是 n n n 的因子。 时间限制:1 s…

SpringBoot(8)-任务

目录 一、异步任务 二、定时任务 三、邮件任务 一、异步任务 使用场景&#xff1a;后端发送邮件需要时间&#xff0c;前端若响应不动会导致体验感不佳&#xff0c;一般会采用多线程的方式去处理这些任务&#xff0c;但每次都需要自己去手动编写多线程来实现 1、编写servic…

React的诞生与发展

React诞生于2013年&#xff0c;由Facebook&#xff08;现Meta&#xff09;的工程师Jordan Walke开发。那时的前端开发还处在jQuery的天下&#xff0c;组件化的概念尚未形成。React的出现犹如一阵春风&#xff0c;为前端开发带来了全新的开发理念和方法论。 React最核心的设计理…

WebStorm 2022.3.2/IntelliJ IDEA 2024.3出现elementUI提示未知 HTML 标记、组件引用爆红等问题处理

WebStorm 2022.3.2/IntelliJ IDEA 2024.3出现elementUI提示未知 HTML 标记、组件引用爆红等问题处理 1. 标题识别elementUI组件爆红 这个原因是&#xff1a; 在官网说明里&#xff0c;才版本2024.1开始&#xff0c;默认启用的 Vue Language Server&#xff0c;但是在 Vue 2 项…

Odoo :免费且开源的农牧行业ERP管理系统

文 / 开源智造Odoo亚太金牌服务 引言 提供农牧企业数字化、智能化、无人化产品服务及全产业链高度协同的一体化解决方案&#xff0c;提升企业智慧种养、成本领先、产业互联的核心竞争力。 行业典型痛点 一、成本管理粗放&#xff0c;效率低、管控弱 产品研发过程缺少体系化…

解决Excel文件流读取数字为时间乱码问题

在将Excel文件流转换为Java中的List时&#xff0c;如果遇到文本被错误地识别为日期格式的问题&#xff0c;这通常是由于Apache POI库在处理单元格数据时默认的行为所导致的。Apache POI会尝试根据单元格的内容自动确定其类型&#xff0c;包括字符串、数字&#xff08;可能解释为…

【Unity踩坑】出现d3d11问题导致编辑器崩溃

升级到Unity 6&#xff0c;有时出现下面这种D3D11的问题&#xff0c;会导致编辑器崩溃。 有人总结了这个问题的解决方法&#xff0c;可以做为参考&#xff1a; Failed to present D3D11 swapchain due to device reset/removed. List of Solutions - Unity Engine - Unity Dis…

数据库基础(MySQL)

1. 数据库基础 1.1 什么是数据库 存储数据用文件就可以了&#xff0c;为什么还要弄个数据库? 文件保存数据有以下几个缺点&#xff1a; 文件的安全性问题文件不利于数据查询和管理文件不利于存储海量数据文件在程序中控制不方便 数据库存储介质&#xff1a; 磁盘内存 为…

JMeter监听器与压测监控之Grafana

Grafana 是一个开源的度量分析和可视化套件&#xff0c;通常用于监控和观察系统和应用的性能。本文将指导你如何在 Kali Linux 上使用 Docker 来部署 Grafana 性能监控平台。 前提条件 Kali Linux&#xff1a;确保你已经安装了 Kali Linux。Docker&#xff1a;确保你的系统已…

集群聊天服务器(13)redis环境安装和发布订阅命令

目录 环境安装订阅redis发布-订阅的客户端编程环境配置客户端编程 功能测试 环境安装 sudo apt-get install redis-server 先启动redis服务 /etc/init.d/redis-server start默认在6379端口上 redis是存键值对的&#xff0c;还可以存链表、数组等等复杂数据结构 而且数据是在…

linux常用指令总结(附Vim编辑器学习总结)

本文是博主对Linux中经常用到的一些指令进行的总结&#xff0c;文章也附带了Linux中经常用到的Vim编辑器的一些基本知识和使用指令&#xff0c;觉得有帮助的朋友可以点赞收藏&#xff01; 本文会持续进行更新 linux常用指令总结 $ pwd # 查看当前终端所在…

w046基于web的古典舞在线交流平台的设计与实现

&#x1f64a;作者简介&#xff1a;多年一线开发工作经验&#xff0c;原创团队&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的网站项目。 代码可以查看文章末尾⬇️联系方式获取&#xff0c;记得注明来意哦~&#x1f339;赠送计算机毕业设计600个选题excel文…

阿里云轻量应用服务器可以用在哪些场景呢

在数字化转型的浪潮中&#xff0c;中小企业面临着如何快速、高效地上云的挑战。阿里云轻量应用服务器&#xff08;SWAS&#xff09;作为一款专为中小企业设计的云服务产品&#xff0c;提供了简单易用、经济实惠的解决方案&#xff0c;助力企业轻松实现云端部署&#xff0c;赋能…

植物明星大乱斗15

能帮到你的话&#xff0c;就给个赞吧 &#x1f618; 文章目录 player.hplayer.cppparticle.hparticle.cpp player.h #pragma once #include <graphics.h> #include "vector2.h" #include "animation.h" #include "playerID.h" #include &…

爬虫开发工具与环境搭建——使用Postman和浏览器开发者工具

第三节&#xff1a;使用Postman和浏览器开发者工具 在网络爬虫开发过程中&#xff0c;我们经常需要对HTTP请求进行测试、分析和调试。Postman和浏览器开发者工具&#xff08;特别是Network面板和Console面板&#xff09;是两种最常用的工具&#xff0c;能够帮助开发者有效地捕…

【操作系统】每日 3 题(二十九)

✍个人博客&#xff1a;https://blog.csdn.net/Newin2020?typeblog &#x1f4e3;专栏地址&#xff1a;https://blog.csdn.net/newin2020/category_12820365.html &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享操作系统面试中常见的面试题给大家~ ❤️…

JSON.stringify的应用说明

前言 JSON.stringify() 方法将 JavaScript 对象转换为字符串,在日常开发中较常用&#xff0c;但JSON.stringify其实有三个参数&#xff0c;后两个参数&#xff0c;使用较少&#xff0c;今天来介绍一下后两个参数的使用场景和示例。 语法及参数说明 JSON.stringify()&#xf…

1.1 如何优化程序性能:cpu和内存的占用上;

1.1 如何优化程序性能&#xff1a;cpu和内存的占用上&#xff1b; 这是两个最大的本地优化策略&#xff1b; 当然&#xff0c;网络程序还需要优化与网络相关的&#xff0c;比如IO loop方式&#xff0c;带宽占用等&#xff1b; 比如&#xff0c;mysql插入性能低&#xff0c;那么…

Orcad 输出有链接属性的PDF

安装adobe pdf安装Ghostscript修改C:\Cadence\SPB_16.6\tools\capture\tclscripts\capUtils\capPdfUtil.tcl ​ 设置默认打印机为 Adobe PDF ​ 将Ghostscript的路径修改正确 打开cadence Orcad &#xff0c;accessories->candece Tcl/Tk Utilities-> Utilities->PD…

React(二)

文章目录 项目地址七、数据流7.1 子组件传递数据给父组件7.1.1 方式一:給父设置回调函数,传递给子7.1.2 方式二:直接将父的setState传递给子7.2 给props传递jsx7.2.1 方式一:直接传递组件给子类7.2.2 方式二:传递函数给子组件7.3 props类型验证7.4 props的多层传递7.5 cla…