BPX-tree
写的匆忙 估计有BUG 修改后 会去掉这个 说明
/** * @author shuly * @date 2017/6/5. */ // hint 一日为叶,终身为叶, 最后还是要转换成 <链表存储节 | 数组> 比较快, 自己写个链表吧 // 先写一个数组的好用一点 class Config { static int M = 8; // 写的不好请确保这是个偶数. static int MIN_NUM = M / 2; } class LinkData { LinkData next; Entry data; LinkData(){ next = null; data = null; } } class Node { int m; Node left; Node right; Entry[] children = new Entry[Config.M]; //LinkData children = new LinkData(); Node(int k) { m = k; left = null; right = null; } } abstract class Entry { Comparable key; } class EntryLeaf extends Entry { Object val; EntryLeaf(Comparable key, Object val) { this.key = key; this.val = val; } } class EntryNotLeaf extends Entry { Node nextNode; EntryNotLeaf(Comparable key, Node next) { this.nextNode = next; this.key = key; } } public class BPXTree<Key extends Comparable<Key>, Value> { private int height; private int total; private Node root; // todo push private Node leafNodeHead; public BPXTree() { leafNodeHead = new Node(0); root = new Node(0); leafNodeHead.right = root; root.left = leafNodeHead; } public int insert(Key key, Value value) { if (key == null) throw new IllegalArgumentException("插入空值我操"); ++total; Node u = insert(root, key, value, height); if (u != null) { Node t = new Node(2); t.children[0] = new EntryNotLeaf(root.children[0].key, root); t.children[1] = new EntryNotLeaf(u.children[0].key, u); root = t; ++height; // 树的生长 } return 1; } /** * @param now 当前插入节点 * @param key key * @param value value * @param h 高度 * @return 需要分裂则但会当前节点,否则是null */ private Node insert(Node now, Key key, Value value, int h) { int j; Entry tmp; if (h == 0) { // 叶子节点 tmp = new EntryLeaf(key, value); for (j = 0; j < now.m; ++j) { if (less(key, now.children[j].key)) { break; } } } else { // 非叶子节点 tmp = new EntryNotLeaf(key, null); for (j = 0; j < now.m; ++j) { if ((j + 1 == now.m) || less(key, now.children[j + 1].key)) { Node u = insert(((EntryNotLeaf) now.children[j++]).nextNode, key, value, h - 1); if (u == null) return null; tmp.key = u.children[0].key; ((EntryNotLeaf) tmp).nextNode = u; break; } } } // 挪地方 for (int i = now.m; i > j; --i) { now.children[i] = now.children[i - 1]; } now.children[j] = tmp; now.m++; if (now.m < Config.M) { return null; } return split(now); } private static Node split(Node now) { int base = Config.M / 2; Node tmp = new Node(base); now.m = base; for (int j = 0; j < base; ++j) { tmp.children[j] = now.children[base + j]; now.children[base + j] = null; } tmp.right = now.right; tmp.left = now; now.right = tmp; return tmp; } public Value query(Key key) { if (key == null) { throw new IllegalArgumentException("查询值是空啊"); } return query(root, key, height); } /** * @param now 当前节点 * @param key 插入的值 * @param h 当前高度 * @return key对应的value, 没有就是null; */ private Value query(Node now, Key key, int h) { Entry[] children = now.children; if (h == 0) {// 叶子节点 for (int j = 0; j < now.m; ++j) { if (eq(key, children[j].key)) { return (Value) ((EntryLeaf) children[j]).val; } } } else { // 非叶子节点 for (int j = 0; j < now.m; ++j) { if ((j + 1 == now.m) || less(key, children[j + 1].key)) { return query(((EntryNotLeaf) children[j]).nextNode, key, h - 1); } } } return null; } public Queue<Value> queue(Key left, Key right) { Queue<Value> ans = new LinkedList<>(); query(root, left, right, height, ans); return ans; } // todo private void query(Node now, Key left, Key right, int h, Queue<Value> ans) { } /** * @param key 删除的关键字 * @return 删除的内容; * <p> * <p> * 切记在合并的时候 要去要别的节点,而不是自己的给别人,也不能去和自己的堂兄弟借,要找兄弟合并。 * 这样才能 递归的更新 索引. 3Q */ public Value delete(Key key) { // root 节点的size没有限制 Triple<Value, Boolean, Key> ans = delete(root, key, height); return ans.first; } /** * @param now 当前节点 * @param key 删除的主键 * @param h 目前的高度 * @return <删除的 映射值, 修改的儿子节点是否足够用, 抢的节点> * <p> * <p> * 采用自己先去抢,抢不到在让父亲节点调度的方式. */ public Triple<Value, Boolean, Key> delete(Node now, Key key, int h) { Triple<Value, Boolean, Key> ans = new Triple<>(null, null, null); if (h == 0) { //叶子了 for (int i = 0; i < now.m; i++) { if (eq(key, now.children[i].key)) { ans.first = (Value) ((EntryLeaf) now.children[i]).val; now.m--; for (int j = i; j < now.m; j++) { now.children[j] = now.children[j + 1]; } now.children[now.m] = null; // 删除吗 不可能 越界 break; } } } else { // 非叶子 节点 // 狗儿子们开始干活了. for (int i = 0; i < now.m; i++) { if ((i + 1 == now.m) || less(key, now.children[i + 1].key)) { // 去吧比卡丘 ans = delete(((EntryNotLeaf) now.children[i]).nextNode, key, h - 1); if (ans.second) { // 操 欲求不满的东西,让我来施舍你! 妈的我 还要维护你们的链接信息,我了个去, int source; int target = i; if (i + 1 == now.m && i != 0) { source = i - 1; Node sourceNode = ((EntryNotLeaf) now.children[source]).nextNode; Node targetNode = ((EntryNotLeaf) now.children[target]).nextNode; for (int w = 0; w < targetNode.m; ++w) { targetNode.children[w + sourceNode.m] = targetNode.children[w]; } for (int s = 0; s < sourceNode.m; s++) { targetNode.children[s] = sourceNode.children[s]; } targetNode.m += sourceNode.m; if(sourceNode.left != null) { sourceNode.left.right = targetNode; } targetNode.left = sourceNode.left; } else { source = i + 1; if (source == now.m) { // 结束了 这是root节点 this.root = ((EntryNotLeaf)root.children[0]).nextNode; this.height--; return ans; } Node sourceNode = ((EntryNotLeaf) now.children[source]).nextNode; Node targetNode = ((EntryNotLeaf) now.children[target]).nextNode; for (int s = 0, t = targetNode.m; s < sourceNode.m; s++, t++) { targetNode.children[t] = sourceNode.children[s]; } targetNode.m += sourceNode.m; targetNode.right = sourceNode.right; if(sourceNode.right != null) { sourceNode.right.left = targetNode; } } // 再见我 的 小伙伴, 满足了你,牺牲了他,何必同室操戈, for (int s = source; s < now.m; s++) { now.children[s] = now.children[s + 1]; } now.m--; now.children[now.m] = null; // 抢东西更新 } else if (ans.third != null && i + 1 != now.m && ans.third.compareTo((Key) now.children[i + 1].key) == 0) { // 借东西索引更新 now.children[i + 1].key = updateIndexUntil(((EntryNotLeaf) now.children[i + 1]).nextNode, ans.third); now.children[i].key = ((EntryNotLeaf)now.children[i]).nextNode.children[0].key; } else { now.children[i].key = ((EntryNotLeaf)now.children[i]).nextNode.children[0].key; } //now.children[i].key = ((EntryNotLeaf)now.children[i]).nextNode.children[0].key; break; } } } ans.second = false; if (now.m < Config.MIN_NUM) { //卧槽节点不够了 if (now.left != null && now.left.m > Config.MIN_NUM) { // left 请给我点吧,我不行了QAQ now.left.m--; Entry entry = now.left.children[now.left.m]; now.left.children[now.left.m] = null; // 这个刁钻的插入操作妈的 for (int i = 1; i <= now.m; ++i) { now.children[i] = now.children[i - 1]; } now.children[0] = entry; now.m++; ans.third = (Key) entry.key; } else if (now.right != null && now.right.m > Config.MIN_NUM) { // right 请给我点吧,我不行了QAQ Entry entry = now.right.children[0]; now.right.m--; for (int i = 0; i < now.right.m; ++i) { now.right.children[i] = now.right.children[i + 1]; } now.right.children[now.right.m] = null; now.children[now.m] = entry; now.m++; // 这个要更新那边 等待到LCA ans.third = (Key) entry.key; } else { // 父亲啊,请给我做主,灭了他们其中一个要不我不满足 ans.second = true; } } return ans; } private Key updateIndexUntil(Node now, Key key) { if (now.children[0].key.compareTo(key) == 0) { now.children[0].key = updateIndexUntil(((EntryNotLeaf)now.children[0]).nextNode, key); } return (Key) now.children[0].key; } @Override public String toString() { return toString(root, height, "") + "\n"; } private String toString(Node h, int ht, String indent) { StringBuilder s = new StringBuilder(); Entry[] children = h.children; if (ht == 0) { for (int j = 0; j < h.m; j++) { s.append(indent).append(children[j].key).append(" ").append(((EntryLeaf) children[j]).val).append("\n"); } } else { for (int j = 0; j < h.m; j++) { s.append(indent).append("(").append(children[j].key).append(")").append("\n"); s.append(toString(((EntryNotLeaf) children[j]).nextNode, ht - 1, indent + " ")); } } return s.toString(); } private static boolean less(Comparable k1, Comparable k2) { return k1.compareTo(k2) < 0; } private static boolean eq(Comparable k1, Comparable k2) { return k1.compareTo(k2) == 0; } private void linkOut() { Node head = this.leafNodeHead; while (head != null) { for (int i = 0; i < head.m; i++) { System.out.print(head.children[i].key + " : " + ((EntryLeaf) head.children[i]).val + '\t'); } head = head.right; } } public static void main(String[] args) { BPXTree<Integer, Long> st = new BPXTree<>(); for (int i = 1; i <= 20; i++) { st.insert(i, (long) i); } Long value = st.delete(10); Long pp = st.delete(9); pp = st.delete(3); pp = st.delete(6); pp = st.delete(1); pp = st.delete(4); pp = st.delete(7); pp = st.delete(2); pp = st.delete(8); pp = st.delete(5); pp = st.delete(11); pp = st.delete(12); pp = st.delete(16); pp = st.delete(17); System.out.println("START"); System.out.println(st.toString()); System.out.println("END"); st.linkOut(); pp = st.delete(18); System.out.println("START"); System.out.println(st.toString()); System.out.println("END"); st.linkOut(); pp = st.delete(19); pp = st.delete(20); pp = st.delete(13); pp = st.delete(14); System.out.println("START"); System.out.println(st.toString()); System.out.println("END"); st.linkOut(); pp = st.delete(15); System.out.println("START"); System.out.println(st.toString()); System.out.println("END"); st.linkOut(); } }