Java实现B树

news2024/11/20 9:20:18

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)) {//从后往前 找出比你小的那个i
                i--;
            }
            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;//树中的最小度数

    //指定默认树的度数是2
    public 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.coloradmin.cn/o/1081419.html

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

相关文章

使用PyTorch处理多维特征输入的完美指南

&#x1f497;&#x1f497;&#x1f497;欢迎来到我的博客&#xff0c;你将找到有关如何使用技术解决问题的文章&#xff0c;也会找到某个技术的学习路线。无论你是何种职业&#xff0c;我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章&#xff0c;也欢…

WorkPlus私有部署即时通信助力企业信息安全与高效协作

在当今快速发展的商业环境中&#xff0c;高效的内部沟通对企业的成功至关重要。然而&#xff0c;在保障信息安全的同时&#xff0c;如何实现高效的协作和沟通一直是企业所面临的挑战。传统的公共即时通信平台&#xff0c;尽管提供了便利的沟通工具&#xff0c;但其数据存储和控…

python- excel 创建/写入/删sheet+花式遍历

文章目录 前言python- excel 创建/写入/删sheet花式遍历1. excel 创建2. 写入excel3. 创建写入excel demo实战4. 删除sheet5. excel 花式遍历 demo实战5.1. 获取 A1的值5.2. 获取指定列的切片数据&#xff0c;获取 B1到B5的值5.3. 循环整个excel的这个sheet5.4. 遍历指定行&…

VR全景云端看车,让你享受不一样的购车体验

这个“黄金周”可谓是热闹非凡&#xff0c;不仅房企大降价&#xff0c;部分车企也在“黄金周”发力&#xff0c;降价优惠促销量&#xff0c;那么你准备买车了吗&#xff1f;买车也是一个大件&#xff0c;需要多家店去走动比对价位&#xff0c;难免会挑花了眼&#xff0c;其实我…

中国SaaS行业等待“渡劫时刻”

期待、追捧、失望、质疑&#xff0c;中国SaaS行业激荡十几年&#xff0c;尝遍了市场浮沉&#xff0c;如今潮水褪去&#xff0c;SaaS企业们到了见真章的时刻。 一开始&#xff0c;SaaS行业被人们寄予厚望。互联网的蓬勃发展&#xff0c;数字化转型的历史进程&#xff0c;似乎都…

快讯|Tubi 有 Rabbit AI 啦

在每月一期的 Tubi 快讯中&#xff0c;你将全面及时地获取 Tubi 最新发展动态&#xff0c;欢迎星标关注【比图科技】微信公众号&#xff0c;一起成长变强&#xff01; Tubi 推出 Rabbit AI 帮助用户找到喜欢的视频内容 Tubi 于今年九月底推出了 Rabbit AI&#xff0c;这是一项…

基于 gin框架搭建入门项目

go mod init gin-ranking go: creating new go.mod: module gin-ranking go: to add module requirements and sums:go mod tidy下载gin框架 cmd窗口中执行命令&#xff1a; go get -u github.com/gin-gonic/ginpackage mainimport ("github.com/gin-gonic/gin"&qu…

圭亚那奥罗拉金矿配电工程中AM5SE系列微机保护装置

安科瑞 崔丽洁 摘要&#xff1a;目前&#xff0c;微机保护装置广泛应用于电力系统中&#xff0c;该类装置能够有效监测电力系统的运行状况&#xff0c;并实时记录电力系统出现故障的位置及性质&#xff0c;从而为故障的快速处理提供有效的参考信息。本文介绍的AM5SE系列微机保…

android:can not find libdevapi.so

一、为什么会出现这样的报错&#xff1f; 引用了一些第三方的sdk的so库之后通常都会遇到这样的错误&#xff0c;&#xff08;“nativeLibraryDirectories”[/data/app/com.lukouapp-1/lib/arm64, /vendor/lib64, /system/lib64]]] couldnt find "libxxxx.so"&#x…

zookeeper节点数据类型介绍及集群搭建

一、zookeeper介绍 zookeeper官网&#xff1a;Apache ZooKeeper zookeeper是一个分布式协调框架&#xff0c;保证的是CP&#xff0c;即一致性和分区容错性&#xff1b;zookeeper是一个分布式文件存储系统&#xff0c;文件节点可以存储数据&#xff0c;监听子文件节点等可以实…

绥化市中心广场焕发新活力:OLED透明拼接屏的奇观展示

OLED透明拼接屏技术在绥化城市的应用引起了广泛关注。 绥化市位于中国东北地区&#xff0c;是黑龙江省的一个重要城市。 该市拥有悠久的历史&#xff0c;历经多个朝代的兴衰。绥化的历史背景赋予了这座城市独特的文化底蕴和魅力。 绥化市内有许多著名景点&#xff0c;其中最…

day

#include <iostream> using namespace std; class Per {//算术运算符friend const Per operator(const Per &k1,const Per &k2);friend const Per operator-(const Per &k1,const Per &k2);friend const Per operator*(const Per &k1,const Per &…

vue项目npm intall时发生版本冲突的解决办法

在日常使用命令npm install / npm install XX下载依赖的操作中&#xff0c;我经常会遇到无法解析依赖树的问题&#xff08;依赖冲突&#xff09; 当遇到这种情况的时候&#xff0c;可以通过以下命令完成依赖安装&#xff1a; npm install --legacy-peer-deps npm install xxx…

国产化即时通讯平台WorkPlus,助力企业实现自主可控的沟通与协作

作为在线沟通与协作的重要工具&#xff0c;即时通讯平台在企业中扮演着不可或缺的角色。然而&#xff0c;为了保护企业的核心数据和机密信息&#xff0c;越来越多的企业开始转向国产化的即时通讯平台。在这一背景下&#xff0c;国内软件品牌WorkPlus应运而生&#xff0c;为企业…

基于 chinese-roberta-wwm-ext 微调训练中文命名实体识别任务

一、模型和数据集介绍 1.1 预训练模型 chinese-roberta-wwm-ext 是基于 RoBERTa 架构下开发&#xff0c;其中 wwm 代表 Whole Word Masking&#xff0c;即对整个词进行掩码处理&#xff0c;通过这种方式&#xff0c;模型能够更好地理解上下文和语义关联&#xff0c;提高中文文…

mongodb简介、安装、搭建复制集

一、 简介 NoSQL数据库四大家族&#xff1a;列存储 Hbase&#xff0c;键值(Key-Value)存储 Redis&#xff0c;图像存储 Neo4j&#xff0c;基于分布式文档存储的数据库MongoDb。 MongoDB 和关系型数据库对比 关系型数据库MongoDBdatabase&#xff08;库&#xff09;database&…

.net也能写内存挂

最近在研究.net的内存挂。 写了很久的c,发现c#写出来的东西实在太香。 折腾c#外挂已经有很长时间了。都是用socket和c配合。 这个模式其实蛮成功的&#xff0c;用rpc调用的方式加上c#的天生await 非常好写逻辑 类似这样 最近想换个口味。注入托管dll到非托管进程 这样做只…

基于 SOFAJRaft 实现注册中心

文章目录 1.前言2.git 示例地址3.官网示例分析3.SOFAJRAFT 注册中心实现&#xff08;服务端&#xff09;3.1 核心功能3.2 模块设计3.3 请求消息数据结构设计3.3.1 Registration 注册消息3.3.2 GetServiceInstancesRequest 获取服务实例请求3.3.3 GetServiceInstancesResponse 获…

Android中级——ListView和RecycleView解析

ListView和RecycleView ListViewRecycleView ListView 使用步骤可看Android基础——ListView&#xff0c;其setAdapter()如下&#xff0c;回调getCount()获取Item个数 Override public void setAdapter(ListAdapter adapter) {if (mAdapter ! null && mDataSetObserv…

v-model绑定input、textarea、checkbox、radio、select

1.input <div><!-- v-model绑定input --><input type"text" v-model"message"><h2>{{message}}</h2></div><script>const App{template:#my-app,data() {return {message:Hello World,}},}Vue.createApp(App).…