首页 > 编程语言 >Java数据结构与算法(B+树)

Java数据结构与算法(B+树)

时间:2024-05-29 20:29:08浏览次数:10  
标签:node getChildren 数据结构 Java pos getKeys 算法 child BPlusTreeNode

前言

B+树(B+ Tree)是一种平衡树数据结构,广泛用于数据库和文件系统中。它是一种自平衡的树结构,每个节点包含多个键,并且所有键都是排序的。B+树的叶子节点包含指向相邻叶子节点的指针,这使得范围查询非常高效。

B+树的优点

1.由于B+树在非叶子结点上不包含真正的数据,只当做索引使用,因此在内存相同的情况下,能够存放更多的key;

2.B+树的叶子结点都是相连的,因此对整棵树的遍历只需要一次线性遍历叶子结点即可。而且由于数据顺序排列并且相连,所以便于区间查找和搜索。而B树则需要进行每一层的递归遍历。

3、B+树与B树相比最明显的其实就是寻址向内存传输这个过程,磁盘向内存中推送数据,每次只能推送一页(4KB)的数据,B树中每一个节点都带有value值,可能一页只能存储一个节点,甚至如果value值过大,可能需要多页,然而,B+树中只有非叶子结点存储value值,上面的节点只存储索引,占用内存就小的多了,可能一次就可以传输完成。

动画过程

B+ Tree Visualization

具体代码实现

package test11;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

class BPlusTreeNode<T extends Comparable<T>> {
    private boolean isLeaf;
    private List<T> keys;
    private List<BPlusTreeNode<T>> children;
    private BPlusTreeNode<T> next;

    public BPlusTreeNode(boolean isLeaf) {
        this.isLeaf = isLeaf;
        this.keys = new ArrayList<>();
        if (!isLeaf) {
            this.children = new ArrayList<>();
        }
    }

    public boolean isLeaf() {
        return isLeaf;
    }

    public List<T> getKeys() {
        return keys;
    }

    public List<BPlusTreeNode<T>> getChildren() {
        return children;
    }

    public BPlusTreeNode<T> getNext() {
        return next;
    }

    public void setNext(BPlusTreeNode<T> next) {
        this.next = next;
    }
}


public class BPlusTree<T extends Comparable<T>> {
    private int order;
    private BPlusTreeNode<T> root;

    public BPlusTree(int order) {
        if (order < 3) {
            throw new IllegalArgumentException("Order of B+ tree must be at least 3");
        }
        this.order = order;
        this.root = new BPlusTreeNode<>(true);
    }

    public void insert(T key) {
        BPlusTreeNode<T> root = this.root;
        if (root.getKeys().size() == order - 1) {
            BPlusTreeNode<T> newRoot = new BPlusTreeNode<>(false);
            newRoot.getChildren().add(root);
            splitChild(newRoot, 0, root);
            this.root = newRoot;
        }
        insertNonFull(this.root, key);
    }

    private void splitChild(BPlusTreeNode<T> parent, int index, BPlusTreeNode<T> child) {
        BPlusTreeNode<T> newChild = new BPlusTreeNode<>(child.isLeaf());
        int mid = order / 2;
        parent.getKeys().add(index, child.getKeys().get(mid));
        parent.getChildren().add(index + 1, newChild);

        newChild.getKeys().addAll(child.getKeys().subList(mid + 1, child.getKeys().size()));
        child.getKeys().subList(mid, child.getKeys().size()).clear();

        if (!child.isLeaf()) {
            newChild.getChildren().addAll(child.getChildren().subList(mid + 1, child.getChildren().size()));
            child.getChildren().subList(mid + 1, child.getChildren().size()).clear();
        } else {
            newChild.setNext(child.getNext());
            child.setNext(newChild);
        }
    }

    private void insertNonFull(BPlusTreeNode<T> node, T key) {
        if (node.isLeaf()) {
            int pos = Collections.binarySearch(node.getKeys(), key);
            if (pos < 0) {
                pos = -(pos + 1);
            }
            node.getKeys().add(pos, key);
        } else {
            int pos = Collections.binarySearch(node.getKeys(), key);
            if (pos < 0) {
                pos = -(pos + 1);
            } else {
                pos++;
            }
            BPlusTreeNode<T> child = node.getChildren().get(pos);
            if (child.getKeys().size() == order - 1) {
                splitChild(node, pos, child);
                if (key.compareTo(node.getKeys().get(pos)) > 0) {
                    pos++;
                }
            }
            insertNonFull(node.getChildren().get(pos), key);
        }
    }

    public boolean search(T key) {
        return search(root, key);
    }

    private boolean search(BPlusTreeNode<T> node, T key) {
        int pos = Collections.binarySearch(node.getKeys(), key);
        if (pos >= 0) {
            return true;
        } else if (node.isLeaf()) {
            return false;
        } else {
            pos = -(pos + 1);
            return search(node.getChildren().get(pos), key);
        }
    }

    public void print() {
        print(root, "", true);
    }

    private void print(BPlusTreeNode<T> node, String indent, boolean last) {
        System.out.print(indent);
        if (last) {
            System.out.print("└─");
            indent += "  ";
        } else {
            System.out.print("├─");
            indent += "| ";
        }
        System.out.println(node.getKeys());
        if (!node.isLeaf()) {
            for (int i = 0; i < node.getChildren().size(); i++) {
                print(node.getChildren().get(i), indent, i == node.getChildren().size() - 1);
            }
        }
    }

    public static void main(String[] args) {
        BPlusTree<Integer> bPlusTree = new BPlusTree<>(3);
        bPlusTree.insert(1);
        bPlusTree.insert(2);
        bPlusTree.insert(3);
        bPlusTree.insert(4);
        bPlusTree.insert(5);

        bPlusTree.print();

        System.out.println("Search 3: " + bPlusTree.search(3));
        System.out.println("Search 6: " + bPlusTree.search(6));
    }
}

QA:待定

标签:node,getChildren,数据结构,Java,pos,getKeys,算法,child,BPlusTreeNode
From: https://blog.csdn.net/acuteeagle01/article/details/139224918

相关文章

  • Erroe:JSON parse error: Cannot deserialize value of type `java.lang.Integer` from
    报错:JSONparseerror:Cannotdeserializevalueoftype`java.lang.Integer`fromObjectvalue(token`JsonToken.START_OBJECT`);nestedexceptioniscom.fasterxml.jackson.databind.exc.MismatchedInputException:Cannotdeserializevalueoftype`java.lang.I......
  • P9 【力扣+知识点】【算法】【二分查找】C++版
    【704】二分查找(模板题)看到复杂度logN,得想到二分给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。示例1:输入:nums=[-1,0,3,5,9,12],target=9输出:4解释:9出现在......
  • 【python数据结构4】基于栈结构的简单括号匹配
    我们现在把注意力转向使用栈解决真正的计算机问题。你会这么写算术表达式(5+6)*(7+8)/(4+3)其中括号用于命令操作的执行。你可能也有一些语言的经验,如Lisp的构造(defunsquare(n)(*nn))这段代码定义了一个名为square的函数,它将返回参数的n的平方。Lisp......
  • “量化之王”的人生算法
    ”量化之王“吉姆·西蒙斯总结自己的五大“人生算法”:1)以美为导向;2)与最聪明、最优秀的人为伍;3)不随波逐流;4)不轻言放弃;5)坚守乐观主义。5月11日,对冲基金文艺复兴科技(RenaissanceTechnologies)的创始人、传奇量化投资大师吉姆·西蒙斯(JimSimons)去世,享年86岁。《金钱心......
  • 数组算法-差分数组
    //差分数组使用背景:区间元素同步增减//差分数组:用来表示原始数组中相邻元素的差值,表示原数组的变化。classex_diff{private:vector<int>diff;public:ex_diff(vector<int>nums){/**求diff[]*diff[i]=nums[i],i......
  • 【KELM回归预测】基于麻雀算法优化核极限学习SSA-KELM-Adaboost实现风电回归预测附mat
    以下是使用麻雀算法优化核极限学习机(SSA-KELM)和Adaboost算法实现风电回归预测的MATLAB代码示例:matlab复制%导入风电数据load(‘wind_data.mat’);%假设数据存储在wind_data.mat文件中X=wind_data(:,1:end-1);%输入特征Y=wind_data(:,end);%输出标签%数......
  • Java项目:205Springboot + vue实现的养老院管理系统(含论文)
    作者主页:夜未央5788 简介:Java领域优质创作者、Java项目、学习资料、技术互助文末获取源码项目介绍基于Springboot+vue实现的养老院管理系统系统包含老人、家属、管理员三个角色系统包含登录、注册、主页、老人管理、家属管理、家属意见管理、寝室管理、老人事故信......
  • 《用ChatGPT轻松搞定Java编程难题:从基础到复杂案例的全面解析》
    ChatGPT国内使用体验点击(文件中并非网站跳转而是详细教程):Docshttps://uajqbcov4oa.feishu.cn/docx/GmeGdznJkoc3nzxHECQcojZ9nXg?from=from_copylink随着人工智能技术的快速发展,越来越多的开发者开始使用ChatGPT来辅助解决编程中的问题。ChatGPT不仅可以快速生成代码,还能进行......
  • java基础
    1.类的概念包:一些接口和类集合在一起,方便使用,类似c语言的头文件使用import关键词,将所用的包导入类:【修饰符】class类名{类体}类中包含构造函数 ,对象(变量),方法等在一个程序中,只有一个pubic类,有一个主类中有main接口,是主程序的接口进入类,用来写一整块的功能【修饰符】包......
  • 升鲜宝供应链管理系统重构版发布(技术点:Java8、mysql8.0 uniapp、vue、android、web 框
    升鲜宝供应链管理系统重构版发布(技术点:Java8、mysql8.0uniapp、vue、android、web框架:Vue3+SpringBoot3),界面功能(三) 主要功能要点:     权限管理(组织机构、用户管理、角色管理、岗位管理)     系统设置(菜单管理、参数管理、数据字典、定时任务、文件管......