Java实现的插入法建立B+树

我所实现的B+树是有关于《数据库系统实现》上的B+书算法的实现。利用插入法,我构建出了一个以long型数据作为键值,以Object型数据为指针的B+索引树。
有关我的程序的说明:
(1)元组数量的取值范围的含义是:本程序中我要生成“要建立元组数”那么多个元组(这里我用Student类代替)并写入文件。每个元组的键值是一个随机长整数(不重复),数量的取值范围其实是指“随机生成的键值的最大值”
(2)要建立的元组数顾名思义,也指代B+树的叶节点的数量(因为每个叶都存放一个指向元组的文件指针)[说明:因为我用RandomAccessFile来存储元组,所以元组的文件指针实际上是一个Long型的数字]
(3)每个节点能容纳的键数量--不懂得看看B+树的定义
(4)桶的数量:引入桶的目的是因为可能要生成很多个不重复的键值,要解决不重复的问题,传统的比较方法时间消耗非常大(O(N)的),引入适量的桶可以加快查找比较的时间。我使用HashSet作为桶,以实现快速建立多个不重复的键值。(当然,要是生成键值少的话就不需要很多桶了--关于桶的概念请查阅向关资料)
(5)文本框中的值是我测试使用的初始值,当你点“复位”的时候,将显示我们老师要求的数值
(6)“要查找的键值”指,你输入一个键值,程序将在书中寻找,并在文本框中给出查找路径(打印出所经过的节点的内容),最后给出你所输入的键值在不在者棵树中。
(7)程序在使用时一定要使用我给的bat文件打开,因为这样可以打开控制台(命令行),因为生成后的树中的键值信息和树的层次信息将在命令行显示。

有关的B+树插入知识:
插入原则上是第归的:(1)设法在适当的叶节点中为新建找到空闲空间,如果有的话,就把键值放在哪里,(2)如果在适当的叶节点中没有空间,就把该叶节点分裂成两个,并且把其中的键分到这两个新节点中,使每个新节点有一半或刚好超过一半的键。(3)某一层的节点分裂在其上一层看来相当于是要在这一较高的层次上插入一个新的键-指针对。因此,我们可以在这一较高层次上第归测试用这个插入策略:如果有空间,就插入;反之则分裂这个入节点且继续相熟的高层推进。(4)例外的情况是,如果试图插入键到跟节点中并且跟节点没有空间,就分裂跟节点成两个节点,在更上一层创建一个新的跟节点。这个新的跟节点有两个刚分裂成的节点作为他的子节点。

友情提示:我的所有代码由JB9生成,压缩包中将附工程文件。由于最近在看《重构》,所以代码中有些风格是从里面学的,但是目前还学艺不精,有点不伦不类,请见谅。我的全部代码放在我的邮箱,要用的到那里去下载,各位抱歉,不会上传图片,大家下载到程序之后就可以看到了:〉
gondam_f91@163.com 密码是012401030

如果程序有BUG,或者看官有什么好的建议,欢迎回复,或发邮件到我的邮箱,我会很乐意与你讨论的。








B树是一种广泛应用于数据库和文件系统中的数据结构,它的主要特点是能够高效地支持插入、查找和删除操作。下面是使用Java实现B树的简单示例代码。 B树节点类: ``` public class BTreeNode { private int t; // B树的度 private int keyNum; // 节点中关键字数量 private int[] keys; // 关键字数组 private boolean isLeaf; // 是否为叶子节点 private BTreeNode[] children; // 子节点数组 public BTreeNode(int t, boolean isLeaf) { this.t = t; this.isLeaf = isLeaf; this.keys = new int[2 * t - 1]; this.children = new BTreeNode[2 * t]; this.keyNum = 0; } public int getKeyNum() { return keyNum; } public int getKey(int index) { return keys[index]; } public void setKey(int index, int key) { keys[index] = key; } public boolean isLeaf() { return isLeaf; } public BTreeNode getChild(int index) { return children[index]; } public void setChild(int index, BTreeNode child) { children[index] = child; } public void setLeaf(boolean isLeaf) { this.isLeaf = isLeaf; } public void setKeyNum(int keyNum) { this.keyNum = keyNum; } } ``` B树类: ``` public class BTree { private BTreeNode root; // B树的根节点 private int t; // B树的度 public BTree(int t) { this.root = null; this.t = t; } // 查找操作 public BTreeNode search(int key) { return search(root, key); } private BTreeNode search(BTreeNode node, int key) { if (node == null) { return null; } int i = 0; while (i < node.getKeyNum() && key > node.getKey(i)) { i++; } if (i < node.getKeyNum() && key == node.getKey(i)) { return node; } if (node.isLeaf()) { return null; } else { return search(node.getChild(i), key); } } // 插入操作 public void insert(int key) { if (root == null) { root = new BTreeNode(t, true); root.setKey(0, key); root.setKeyNum(1); } else { if (root.getKeyNum() == 2 * t - 1) { BTreeNode newRoot = new BTreeNode(t, false); newRoot.setChild(0, root); root = newRoot; splitChild(root, 0); } insertNonFull(root, key); } } private void insertNonFull(BTreeNode node, int key) { int i = node.getKeyNum() - 1; if (node.isLeaf()) { while (i >= 0 && key < node.getKey(i)) { node.setKey(i + 1, node.getKey(i)); i--; } node.setKey(i + 1, key); node.setKeyNum(node.getKeyNum() + 1); } else { while (i >= 0 && key < node.getKey(i)) { i--; } i++; if (node.getChild(i).getKeyNum() == 2 * t - 1) { splitChild(node, i); if (key > node.getKey(i)) { i++; } } insertNonFull(node.getChild(i), key); } } private void splitChild(BTreeNode node, int i) { BTreeNode y = node.getChild(i); BTreeNode z = new BTreeNode(t, y.isLeaf()); z.setKeyNum(t - 1); for (int j = 0; j < t - 1; j++) { z.setKey(j, y.getKey(j + t)); } if (!y.isLeaf()) { for (int j = 0; j < t; j++) { z.setChild(j, y.getChild(j + t)); } } y.setKeyNum(t - 1); for (int j = node.getKeyNum(); j >= i + 1; j--) { node.setChild(j + 1, node.getChild(j)); } node.setChild(i + 1, z); for (int j = node.getKeyNum() - 1; j >= i; j--) { node.setKey(j + 1, node.getKey(j)); } node.setKey(i, y.getKey(t - 1)); node.setKeyNum(node.getKeyNum() + 1); } // 删除操作 public void delete(int key) { if (root == null) { return; } delete(root, key); if (root.getKeyNum() == 0) { root = root.getChild(0); } } private void delete(BTreeNode node, int key) { int i = 0; while (i < node.getKeyNum() && key > node.getKey(i)) { i++; } if (i < node.getKeyNum() && key == node.getKey(i)) { if (node.isLeaf()) { for (int j = i + 1; j < node.getKeyNum(); j++) { node.setKey(j - 1, node.getKey(j)); } node.setKeyNum(node.getKeyNum() - 1); } else { BTreeNode leftChild = node.getChild(i); BTreeNode rightChild = node.getChild(i + 1); if (leftChild.getKeyNum() >= t) { int pred = getPredecessor(node, i); node.setKey(i, pred); delete(leftChild, pred); } else if (rightChild.getKeyNum() >= t) { int succ = getSuccessor(node, i); node.setKey(i, succ); delete(rightChild, succ); } else { merge(node, i); delete(leftChild, key); } } } else { if (node.isLeaf()) { return; } boolean flag = (i == node.getKeyNum()); BTreeNode child = node.getChild(i); if (child.getKeyNum() < t) { fill(node, i); } if (flag && i > node.getKeyNum()) { delete(node.getChild(i - 1), key); } else { delete(node.getChild(i), key); } } } private int getPredecessor(BTreeNode node, int index) { BTreeNode cur = node.getChild(index); while (!cur.isLeaf()) { cur = cur.getChild(cur.getKeyNum()); } return cur.getKey(cur.getKeyNum() - 1); } private int getSuccessor(BTreeNode node, int index) { BTreeNode cur = node.getChild(index + 1); while (!cur.isLeaf()) { cur = cur.getChild(0); } return cur.getKey(0); } private void fill(BTreeNode node, int index) { if (index != 0 && node.getChild(index - 1).getKeyNum() >= t) { borrowFromPrev(node, index); } else if (index != node.getKeyNum() && node.getChild(index + 1).getKeyNum() >= t) { borrowFromNext(node, index); } else { if (index != node.getKeyNum()) { merge(node, index); } else { merge(node, index - 1); } } } private void borrowFromPrev(BTreeNode node, int index) { BTreeNode child = node.getChild(index); BTreeNode sibling = node.getChild(index - 1); for (int i = child.getKeyNum() - 1; i >= 0; i--) { child.setKey(i + 1, child.getKey(i)); } if (!child.isLeaf()) { for (int i = child.getKeyNum(); i >= 0; i--) { child.setChild(i + 1, child.getChild(i)); } } child.setKey(0, node.getKey(index - 1)); if (!sibling.isLeaf()) { child.setChild(0, sibling.getChild(sibling.getKeyNum())); } node.setKey(index - 1, sibling.getKey(sibling.getKeyNum() - 1)); child.setKeyNum(child.getKeyNum() + 1); sibling.setKeyNum(sibling.getKeyNum() - 1); } private void borrowFromNext(BTreeNode node, int index) { BTreeNode child = node.getChild(index); BTreeNode sibling = node.getChild(index + 1); child.setKey(child.getKeyNum(), node.getKey(index)); if (!child.isLeaf()) { child.setChild(child.getKeyNum() + 1, sibling.getChild(0)); } node.setKey(index, sibling.getKey(0)); for (int i = 1; i < sibling.getKeyNum(); i++) { sibling.setKey(i - 1, sibling.getKey(i)); } if (!sibling.isLeaf()) { for (int i = 1; i <= sibling.getKeyNum(); i++) { sibling.setChild(i - 1, sibling.getChild(i)); } } child.setKeyNum(child.getKeyNum() + 1); sibling.setKeyNum(sibling.getKeyNum() - 1); } private void merge(BTreeNode node, int index) { BTreeNode child = node.getChild(index); BTreeNode sibling = node.getChild(index + 1); child.setKey(t - 1, node.getKey(index)); for (int i = 0; i < sibling.getKeyNum(); i++) { child.setKey(i + t, sibling.getKey(i)); } if (!child.isLeaf()) { for (int i = 0; i <= sibling.getKeyNum(); i++) { child.setChild(i + t, sibling.getChild(i)); } } for (int i = index + 1; i < node.getKeyNum(); i++) { node.setKey(i - 1, node.getKey(i)); } for (int i = index + 2; i <= node.getKeyNum(); i++) { node.setChild(i - 1, node.getChild(i)); } child.setKeyNum(2 * t - 1); node.setKeyNum(node.getKeyNum() - 1); } } ``` 这是一个简单的B树实现,仅供参考。在实际应用中,可能需要根据具体情况进行优化和改进。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值