B树
书上和各种资料对B树的定义有很多
下面是一种B树节点的定义和插入实现(java)
import java.util.LinkedList; public class BTreeNode { /** * B-树阶数 */ int m; /** * 节点关键字列表 */ LinkedList<Integer> values; /** * 节点父节点 */ BTreeNode parent; /** * 节点的孩子节点列表 */ LinkedList<BTreeNode> children; public BTreeNode() { values = new LinkedList<>(); children = new LinkedList<>(); } public BTreeNode(int m) { this(); if (m < 3) { throw new RuntimeException("The order of B-Tree should be greater than 2."); } this.m = m; } /** * 根据父亲节点构造孩子节点 * * @param parent */ public BTreeNode(BTreeNode parent) { this(parent.m); this.parent = parent; } public BTreeNode insert(int e) { if (isEmpty()) { values.add(e); children.add(new BTreeNode(this)); children.add(new BTreeNode(this)); return this; } BTreeNode p = getRoot().search(e); if (!p.isEmpty()) { throw new RuntimeException("cannot insert duplicate key to B-Tree, key: " + e); } return p; } /** * 向指定节点内插入关键字和关键字右侧的孩子节点 * * @param node * @param e * @param eNode 待插入节点的右侧孩子节点 */ private void insertNode(BTreeNode node, int e, BTreeNode eNode) { int valueIndex = 0; //寻找节点插入的位置 while (valueIndex < node.values.size() && e < node.values.get(valueIndex)) { valueIndex++; } //插入节点 node.values.add(valueIndex, e); eNode.parent = node; //插入孩子节点 node.children.add(valueIndex + 1, eNode); //判断是否需要分裂节点 if (node.values.size() > m - 1) { //分裂位置 int upIndex = m / 2; int up = node.values.get(upIndex); // 当前节点分为左右两部分,左部的父节点不变,右部的父节点放在上升关键字右侧 BTreeNode rNode = new BTreeNode(m); rNode.values = new LinkedList<>(node.values.subList(upIndex + 1, m)); rNode.children = new LinkedList<>(node.children.subList(upIndex, m + 1)); //因为当前rNode.children的父节点是node 所以将它们指向rNode for (BTreeNode child : rNode.children) { child.parent = rNode; } node.values = new LinkedList<>(node.values.subList(0, upIndex)); node.children = new LinkedList<>(node.children.subList(0, upIndex + 1)); /** * 显然 这是个递归函数 递归结束的条件有两个 第一个是不满足上面的if判断条件 自然不会进入递归函数中 * 第二个就是当前node节点已经是根节点 显然意味着是根节点关键字数量超出。 * 此时需要产生一个新的根节点 如下面代码所示 */ if (node.parent == null) { node.parent = new BTreeNode(m); node.parent.values.add(up); node.parent.children.add(node); node.parent.children.add(rNode); return; } insertNode(node.parent, up, rNode); } } /** * 判断节点是否为空 * * @return */ public boolean isEmpty() { if (values == null || values.size() == 0) { return true; } return false; } /** * 获取根节点 * * @return */ public BTreeNode getRoot() { BTreeNode p = this; while (!p.isRoot()) { p = p.parent; } return p; } /** * 判断是不是根节点 * * @return */ public boolean isRoot() { return parent == null; } /** * 从当前节点往下查找目标值target * * @param target * @return 找到则返回找到的节点,不存在则返回叶子节点 */ public BTreeNode search(int target) { if (isEmpty()) { return this; } int valueIndex = 0; while (valueIndex < values.size() && values.get(valueIndex) <= target) { if (values.get(valueIndex) == target) { return this; } valueIndex++; } /** * children.get(valueIndex)表示当前节点的最后一个孩子节点 * 因为当前节点都找完之后 那么值只有可能出现在当前节点的最后的孩子节点(按照节点大小关系) */ return children.get(valueIndex).search(target); } } import java.util.LinkedList; public class BTreeNode { /** * B-树阶数 */ int m; /** * 节点关键字列表 */ LinkedList<Integer> values; /** * 节点父节点 */ BTreeNode parent; /** * 节点的孩子节点列表 */ LinkedList<BTreeNode> children; public BTreeNode() { values = new LinkedList<>(); children = new LinkedList<>(); } public BTreeNode(int m) { this(); if (m < 3) { throw new RuntimeException("The order of B-Tree should be greater than 2."); } this.m = m; } /** * 根据父亲节点构造孩子节点 * * @param parent */ public BTreeNode(BTreeNode parent) { this(parent.m); this.parent = parent; } public BTreeNode insert(int e) { if (isEmpty()) { values.add(e); children.add(new BTreeNode(this)); children.add(new BTreeNode(this)); return this; } BTreeNode p = getRoot().search(e); if (!p.isEmpty()) { throw new RuntimeException("cannot insert duplicate key to B-Tree, key: " + e); } return p; } /** * 向指定节点内插入关键字和关键字右侧的孩子节点 * * @param node * @param e * @param eNode 待插入节点的右侧孩子节点 */ private void insertNode(BTreeNode node, int e, BTreeNode eNode) { int valueIndex = 0; //寻找节点插入的位置 while (valueIndex < node.values.size() && e < node.values.get(valueIndex)) { valueIndex++; } //插入节点 node.values.add(valueIndex, e); eNode.parent = node; //插入孩子节点 node.children.add(valueIndex + 1, eNode); //判断是否需要分裂节点 if (node.values.size() > m - 1) { //分裂位置 int upIndex = m / 2; int up = node.values.get(upIndex); // 当前节点分为左右两部分,左部的父节点不变,右部的父节点放在上升关键字右侧 BTreeNode rNode = new BTreeNode(m); rNode.values = new LinkedList<>(node.values.subList(upIndex + 1, m)); rNode.children = new LinkedList<>(node.children.subList(upIndex, m + 1)); //因为当前rNode.children的父节点是node 所以将它们指向rNode for (BTreeNode child : rNode.children) { child.parent = rNode; } node.values = new LinkedList<>(node.values.subList(0, upIndex)); node.children = new LinkedList<>(node.children.subList(0, upIndex + 1)); /** * 显然 这是个递归函数 递归结束的条件有两个 第一个是不满足上面的if判断条件 自然不会进入递归函数中 * 第二个就是当前node节点已经是根节点 显然意味着是根节点关键字数量超出。 * 此时需要产生一个新的根节点 如下面代码所示 */ if (node.parent == null) { node.parent = new BTreeNode(m); node.parent.values.add(up); node.parent.children.add(node); node.parent.children.add(rNode); return; } insertNode(node.parent, up, rNode); } } /** * 判断节点是否为空 * * @return */ public boolean isEmpty() { if (values == null || values.size() == 0) { return true; } return false; } /** * 获取根节点 * * @return */ public BTreeNode getRoot() { BTreeNode p = this; while (!p.isRoot()) { p = p.parent; } return p; } /** * 判断是不是根节点 * * @return */ public boolean isRoot() { return parent == null; } /** * 从当前节点往下查找目标值target * * @param target * @return 找到则返回找到的节点,不存在则返回叶子节点 */ public BTreeNode search(int target) { if (isEmpty()) { return this; } int valueIndex = 0; while (valueIndex < values.size() && values.get(valueIndex) <= target) { if (values.get(valueIndex) == target) { return this; } valueIndex++; } /** * children.get(valueIndex)表示当前节点的最后一个孩子节点 * 因为当前节点都找完之后 那么值只有可能出现在当前节点的最后的孩子节点(按照节点大小关系) */ return children.get(valueIndex).search(target); } }