Java实现B树

1.介绍

B树是一种自平衡的搜索树数据结构,常用于数据库和文件系统中的索引结构。它具有以下好处和功能:

  1. 高效的查找操作:B树的特点是每个节点可以存储多个关键字,并且保持有序。通过在节点上进行二分查找,可以快速定位目标关键字的位置,从而实现高效的查找操作。

  2. 平衡性:B树通过自平衡的方式维护树的平衡性,即保证树的每个叶子节点到根节点的路径长度相等。这种平衡性能够确保各种操作的时间复杂度保持在较低水平,例如插入、删除和查找等操作都可以在对数时间内完成。

  3. 适应大型数据集:B树适用于存储大型数据集,并且可以处理非常大的索引。其节点可以存储多个关键字,因此在相同层数的情况下,B树可以存储更多的数据。

  4. 支持范围查询:由于B树的节点有序,因此可以很方便地进行范围查询。通过定位范围的起始和结束关键字所在的节点,可以快速地获取指定范围内的数据。

  5. 高效的插入和删除操作:B树通过平衡性的维护,使得插入和删除操作具有较低的时间复杂度。它可以通过调整节点的结构,避免过深或过浅的树结构,从而保持树的平衡。

总的来说,B树是一种高效的数据结构,能够应对大规模数据集的索引需求,并提供快速的查找、插入和删除操作。它在数据库和文件系统中广泛应用,为数据的组织和访问提供了便利。

2.代码分析

1.分裂

当键的数量超过 2t - 1的时候就会进行分裂操作,规则就是中间的向上分裂,大的交给一个新的节点,小的交给自己

如果不是叶子节点就需要把后半部分子节点给新的节点,

2.添加

  1. 首先,根据给定的关键字,从根节点开始向下搜索,找到合适的叶子节点。

  2. 在叶子节点中插入新的关键字。如果叶子节点未满,直接插入;否则,执行步骤3。

  3. 当叶子节点已满时,需要进行分裂操作。将当前节点一分为二,得到两个新的叶子节点,并选择一个关键字提升到父节点中。

  4. 如果父节点也已满,则重复步骤3,层层递归地向上分裂,直到找到一个非满节点或达到树的顶部。

  5. 完成插入操作后,需要更新祖先节点的关键字信息。如果某个节点发生了分裂,它提升的关键字需要插入到其父节点中,并根据大小顺序进行调整。

通过以上步骤,B树的插入操作可以保持树的平衡性。在插入过程中,B树会根据节点的容量进行自动调整,使得树的高度保持相对较低,从而确保各种操作的效率。

需要注意的是,在插入操作中可能会出现关键字重复的情况。对于B树来说,可以允许存在相同的关键字,而在查找操作时,会按照节点中关键字的大小顺序进行搜索。因此,在插入过程中需要根据具体需求来处理关键字重复的情况。

3.查找

  1. 从根节点开始,比较要查找的关键字与当前节点中的关键字。

  2. 如果找到了匹配的关键字,则表示查找成功,结束操作。

  3. 如果要查找的关键字小于当前节点的最小关键字,则进入当前节点的左子树进行继续查找。

  4. 如果要查找的关键字大于当前节点的最大关键字,则进入当前节点的右子树进行继续查找。

  5. 重复步骤 3 和 4,直到找到匹配的关键字或者到达叶子节点。

  6. 如果到达叶子节点仍然没有找到匹配的关键字,则表示查找失败,结束操作。

在B树的查找过程中,关键字的比较会指导搜索方向,通过不断地按照关键字的大小顺序向下搜索,可以快速地找到目标关键字或者判断其不存在。

需要注意的是,B树中允许存在相同的关键字,因此在查找操作中,如果存在多个相同的关键字,可以根据具体需求选择返回其中一个或全部。此外,B树的查找操作具有较好的平均时间复杂度,可以在较短的时间内完成查询。

3.代码实现

1.准备工作

//节点类
class BTreeNode {// B树的阶数int t;List<Integer> keys;//关键字List<BTreeNode> childNodes;//孩子boolean leaf;//判断节点是否是叶子结点public BTreeNode(int t, boolean leaf) {this.t = t;this.leaf = leaf;this.keys = new ArrayList<>();this.childNodes = new ArrayList<>();}
}

2.升序遍历树

 public void traverse() {int i;for (i = 0; i < keys.size(); i++) {if (!leaf) {//去索引为i的孩子里面继续找childNodes.get(i).traverse();}System.out.print(keys.get(i) + " ");}//最后还剩一个关键字的孩子节点if (!leaf) {childNodes.get(i).traverse();}}

3.查找值所在的位置

 public int search(int key) {int i = 0;//先找到比值小和等的节点 然后小的递归找孩子while (i < keys.size() && key > keys.get(i)) {i++;}//等的if (i < keys.size() && key == keys.get(i)) {return i;} else if (leaf) {//都到叶子了还没找到就无了return -1;} else {//递归继续去他的子节点找  小的return childNodes.get(i).search(key);}}

4.添加

 public void insertNonFull(int key) {//处理节点未满的情况int i = keys.size() - 1;if (leaf) {//叶节点while (i >= 0 && key < keys.get(i)) {//从后往前 找出比你小的那个ii--;}keys.add(i + 1, key);//因为第i个位置是比你小的,所以你要插入后面一个} else {//非叶节点while (i >= 0 && key < keys.get(i)) {//找到要插入子节点的位置i--;}//判断子节点是否需要分裂操作if (childNodes.get(i + 1).keys.size() == (2 * t) - 1) {splitChild(i + 1, childNodes.get(i + 1));if (key > keys.get(i + 1)) {i++;}}//分裂完毕 或者 不需要分裂 递归插入childNodes.get(i + 1).insertNonFull(key);}}

5.分裂

 public void splitChild(int i, BTreeNode y) {//处理节点满的情况进行分裂操作BTreeNode z = new BTreeNode(y.t, y.leaf);keys.add(i, y.keys.get(t - 1));//中间的上移childNodes.add(i + 1, z);//创建新的孩子for (int j = 0; j < t - 1; j++) {//后面的移动到新的里面z.keys.add(j, y.keys.get(j + t));}if (!y.leaf) {//后半部分子节点移动到新的节点for (int j = 0; j < t; j++) {z.childNodes.add(j, y.childNodes.get(j + t));}}//主要总用时为了情况没有用的部分//获取被拆分节点后半部分的关键字和子节点部分。y.keys.subList(t - 1, y.keys.size()).clear();//方法用于删除列表中的元素(获取完删除)y.childNodes.subList(t, y.childNodes.size()).clear();}
}

6.遍历查询

class BTree {BTreeNode root;//根节点int t;//树中的最小度数//指定默认树的度数是2public BTree() {this(2);}public BTree(int t) {this.root = null;this.t = t;}//遍历树public void traverse() {//树不为空就可以遍历if (root != null) {root.traverse();}}//查找节点的位置public int search(int key) {if (root != null) {return root.search(key);}return -1;}//插入节点public void insert(int key) {if (root == null) {root = new BTreeNode(t, true);root.keys.add(0, key);} else {if (root.keys.size() == (2 * t) - 1) {BTreeNode s = new BTreeNode(t, false);s.childNodes.add(0, root);s.splitChild(0, root);int i = 0;if (s.keys.get(0) < key) {i++;}s.childNodes.get(i).insertNonFull(key);root = s;} else {root.insertNonFull(key);}}}
}

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

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

相关文章

Ubuntu22.04.3安装教程

虚拟机系列文章 VMware Workstation Player 17 免费下载安装教程 VMware Workstation 17 Pro 免费下载安装教程 windows server 2012安装教程 Ubuntu22.04.3安装教程 FTP服务器搭建 Ubuntu22.04.3安装教程 虚拟机系列文章前言Ubuntu22.04.3安装&#xff08;图文&#xff09; 前…

2ED2410-EM:12v / 24v智能模拟高侧MOSFET栅极驱动器

概述 12v / 24v智能模拟高侧MOSFET栅极驱动器。 特性 PRO-SIL ISO 26262-准备根据ISO 26262:2018条款8-13支持硬件元件评估的集成商。一个通道器件具有两个高侧栅极驱动器输出。3 Ω下拉,50 Ω上拉,用于快速开关开/关。支持背靠背MOSFET拓扑(共漏极和共源)。两个双向高侧模拟…

STM32:GPIO模拟SPI驱动ADS8361

ADS8361是TI公司开发的一款模拟量输入芯片。ADS8361有四种工作模式&#xff0c;本文主要针对模式三进行通信驱动。官方方案使用两路SPI来通信&#xff0c;一路SPI Master&#xff0c;一路SPI Slave。我在使用STM32主控芯片的两路SPI进行通信的时候&#xff0c;发现只有SPI Mast…

swift ui 布局 ——Stack(HStack、VStack、ZStack)

一、HStack 水平布局 将其子视图排列在水平线上 import Foundation import SwiftUI struct MyView: View {var body: some View {HStack{Text("text")Image("yuyin").resizable().frame(width: 102,height: 80)}} } 默认子视图是水平中心对齐的,可添加al…

软件测试学习(一)基础概念、实质、说明书测试、分类、动态黑盒测试

软件测试概念、背景 软件无处不在。然而&#xff0c;软件是人写的一所以不完美。 世界上有完美的软件吗&#xff1f;NO 世界上没有完美的软件。所有软件都可能存在缺陷、错误或漏洞&#xff0c;无论是操作系统、应用程序、游戏还是其他类型的软件。这些问题可能会导致功能问题…

【高等数学】极限(上)(最全万字详解)

文章目录 1、数列的极限1.1、数列极限的定义1.2、为什么收敛数列极限是唯一的&#xff1f;1.3、为什么收敛数列是有界的&#xff1f;1.4、数列极限的保号性1.4.1、极限保数列值1.4.2、数列值保极限值 1.5、收敛数列与其子列之间的关系 2、函数极限概念2.1、函数极限的定义2.1.1…

tomcat服务安装步骤以及详细配置教程

tomcat服务安装步骤以及详细配置教程 文章目录 tomcat服务安装步骤以及详细配置教程1.简介2.优缺点优点&#xff1a;缺点&#xff1a; 3.工作原理4.工作流程5.实战&#xff08;tomcat项目部署&#xff09;5.1.java环境安装5.2.拉取tomcat软件包5.3.解压部署5.4.启动tomcat服务5…

conda: error: argument COMMAND: invalid choice: ‘activate‘

参考:https://github.com/conda/conda/issues/13022 输入后重启terminal即可

git push错误->Error: src refspec master does not match any

参考:https://blog.csdn.net/weixin_40908748/article/details/128574907 问题描述&#xff1a;在执行命令 git push origin master 时报错->Error: src refspec master does not match any 问题分析&#xff1a;在网上查找解决方法&#xff0c;大部分人说是暂存区没有文件…

zsh: command not found: conda问题解决

参考:https://zhuanlan.zhihu.com/p/158703094 一、问题介绍与环境介绍 系统为macOS Catalina 10.15.4 所用终端为zsh 安装了oh-my-zsh之后conda命令在终端中不可用。 二、原因分析 终端中zsh的可访问的程序一般放在/bin, /usr/bin, /usr/local/bin&#xff0c;/bin目录下&…

阿里云上了新闻联播

我是卢松松&#xff0c;点点上面的头像&#xff0c;欢迎关注我哦&#xff01; 阿里新任的CEO吴泳铭上央视新闻联播了! 在昨天的新闻联播里&#xff0c;出席科技座谈会&#xff0c;有一个特别镜头&#xff0c;出现了阿里新任CEO吴泳铭的镜头。 这个信号意义明显&#xff0c;我…

L14D6内核模块编译方法

一、内核模块基础代码解析 一个内核模块代码错误仍然会导致的内核崩溃。 GPL协议&#xff1a;开源规定&#xff0c;使用内核一些函数需要 1、单内核的缺点 单内核扩展性差的缺点减小内核镜像文件体积&#xff0c;一定程度上节省内存资源提高开发效率不能彻底解决稳定性低的缺…

如何在 Keras 中开发具有注意力的编码器-解码器模型

link 【翻译自 &#xff1a; How to Develop an Encoder-Decoder Model with Attention in Keras 】 【说明&#xff1a;Jason Brownlee PhD大神的文章个人很喜欢&#xff0c;所以闲暇时间里会做一点翻译和学习实践的工作&#xff0c;这里是相应工作的实践记录&#xff0c;…

Vue-1.9工程化开发和脚手架

开发Vue的两种方式&#xff1a; 1.核心包传统开发模式&#xff1a;基于html/css/js文件&#xff0c;直接引入核心包&#xff0c;开发Vue 2.工程化开发模式&#xff1a;基于构建工具&#xff08;例如&#xff1a;webpack&#xff09;的环境中开发Vue 问题&#xff1a; 1&…

排序算法-选择排序法(SelectionSort)

排序算法-选择排序法&#xff08;SelectionSort&#xff09; 1、说明 选择排序法也是枚举法的应用&#xff0c;就是反复从未排序的数列中取出最小的元素&#xff0c;加入另一个数列中&#xff0c;最后的结果即为已排序的数列。选择排序法可使用两种方式排序&#xff0c;即在所…

XML是不是主要用做配置文件?

2023年10月11日&#xff0c;周三下午 这几天发现tomcat的配置文件主要是用XML文件来写的&#xff0c; 于是就有了这个问题。 是的,XML非常适合用来做配置文件。 XML作为配置文件的主要优点: 可读性强。XML使用标签结构组织数据,内容清晰易懂。跨语言和跨平台。XML作为纯文本…

Fisher辨别分析

问题要求 在UCI数据集上的Iris和Sonar数据上验证算法的有效性。训练和测试样本有三种方式&#xff08;三选一&#xff09;进行划分&#xff1a; &#xff08;一&#xff09; 将数据随机分训练和测试&#xff0c;多次平均求结果 &#xff08;二&#xff09;K折交叉验证 &…

vscode 资源管理器移动到右边

目录 vscode 资源管理器移动到右边 vscode 资源管理器移动到右边 点击 文件》首选项》设置》工作台》外观》 找到这个配置下拉选择左右

排序算法-插入排序法(InsertSort)

排序算法-插入排序法&#xff08;InsertSort&#xff09; 1、说明 插入排序法是将数组中的元素逐一与已排序好的数据进行比较&#xff0c;先将前两个元素排序好&#xff0c;再将第三个元素插入适当的位置&#xff0c;也就是说这三个元素仍然是已排序好的&#xff0c;接着将第…

Rust入门基础

文章目录 Rust相关介绍为什么要用Rust&#xff1f;Rust的用户和案例 开发环境准备安装Rust更新与卸载Rust开发工具 Hello World程序编写Rust程序编译与运行Rust程序 Cargo工具Cargo创建项目Cargo构建项目Cargo构建并运行项目Cargo检查项目Cargo为发布构建项目 Rust相关介绍 为…