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();
    }
}

 

posted @ 2017-07-31 10:08  默默无语敲代码  阅读(171)  评论(0编辑  收藏  举报