实现B树的删除方法时出错

时间:2015-03-21 21:41:18

标签: java b-tree

我正在尝试实现B树并坚持删除方法。当节点中键值对的数量小于预定数量M的一半,即M / 2时,则需要组合连续节点。我遇到一个IndexOutOfBound错误,当我需要删除节点的第一个子元素中的元素时会发生这种错误。这是删除方法:

public Value delete(Key key){
        return (Value) delete(root, key, HT).value;
    }
    private Entry delete(Node h, Key key, int ht){
        Entry[] children = h.children;
        int j = 0;
        if(ht == 0){
            for(; j < h.m; j++){
                if(children[j].key.equals(key)){
                    break;
                }
            }
        }else {
            for(;j < h.m; j++){
                if(j + 1 == h.m || key.compareTo((Key) children[j + 1].key) < 0){
                    Entry deleted = delete(children[j].next, key, ht - 1);
                    if(children[j].next.m < M / 2){
                        children[j].next = combine(children[j - 1].next, children[j].next);
                        if(children[j].next.m == 0)
                            break;
                    }
                    return deleted;
                }
            }
        }
        Entry toReturn = children[j];
        for(int i = j; i < h.m; i++){
            children[i] = children[i + 1];
        }
        h.m--;
        N--;
        //if(h.m == 0)
            //h = null;
        return toReturn;
    }
    private Node combine(Node a, Node b){
        int size = a.m;
        for (int i = size; i < size + b.m; i++){
            a.children[i] = b.children[i - b.m];
            a.m++;
        }
        if(a.m < M)
            b.m = 0;
        else
            b = split(a);
        return b;
    }

这是全班,插入和搜索方法可以编译得很好。

public class BTree <Key extends Comparable<Key>, Value>{
    //maximum children per B-tree
    private static int M;
    private Node root;
    //height of the B-tree
    private int HT;
    //number of key-value pairs in the B-tree
    private int N;
    /***************************************************************
     * private class for the node
     ***************************************************************/
    /**
     * tree node class
     * Entry list is used for all key - value pairs stored in the node
     * m is the index of the pair with the largest key
     * since its 0 index, the node contains m + 1 key - value pairs
     * @author shirleyyoung
     *
     */
    private static class Node{
        private int m;//current number of key-value pairs, as well as the index where next key-value pair will be added
        private Entry[] children = new Entry[M];//the array for the key value pair, different from the children of a tree
        private Node(int k){
            m = k;
        }
    }
    /**
     * The structure to store the key-value pairs
     * @author shirleyyoung
     *
     */
    private static class Entry implements Comparable<Entry>{
        private Comparable key;
        private Object value;
        private Node next;
        public Entry(Comparable key, Object value, Node next){
            this.key = key;
            this.value = value;
            this.next = next;
        }

        public int compareTo(Entry e) {
            return key.compareTo(e.key);
        }
    }

    /*******************************************************
     * constructor
     * M is the maximum key-value pairs a node can store, 
     * it should be an even value for the sake of split
     * @param M
    ********************************************************/
    public BTree(int M){
        if(M % 2 != 0)
            throw new IllegalArgumentException("Maximum children must be an even number!");
        this.M = M;
        HT = 0;
        N = 0;
        root = new Node(0);
    }

    /******************************************************
     * search for an object
    *******************************************************/
    public Value get(Key key){
        return (Value) search(root, key, HT).value;
    }
    //ht:current height
    private Entry search(Node x, Key key, int ht){
        Entry[] children = x.children;
        //root
        if(ht == 0){
            for(int j = 0; j < x.m; j++){
                if(key.equals(children[j].key))
                    return children[j];
            }
        } else{//internal nodes
            for(int j = 0; j < x.m; j++){
                if(j == x.m - 1|| key.compareTo((Key) children[j + 1].key) < 0)
                    return search(children[j].next, key, ht - 1);
            }
        }
        return null;
    }


    /***************************************************
     * Insertion
     ***************************************************/
    public void put(Key key, Object value){
        Entry tmp = search(root, key, HT);
        if(tmp != null){
            tmp.value = value;
            return;
        }
        Node u = insert(root, key, value, HT);
        N++;
        if(u == null) return;

        //if the previous node is split, initialize a new node as the root
        Node t = new Node(2);//2 children
        t.children[0] = new Entry(root.children[0].key, null, root);
        t.children[1] = new Entry(u.children[0].key, null, u);
        root = t;
        HT++;

    }
    private Node insert(Node h, Key key, Object value, int ht){
        int j;
        //the key-value pair to be added
        Entry toAdd = new Entry(key, value, null);
        if(ht == 0){
            //find the correct place to insert the value
            for(j = 0; j < h.m; j++){
                if(key.compareTo((Key) h.children[j].key) < 0)
                    break;
            }
        }else {
            for(j = 0; j < h.m; j++){
                if((j + 1 == h.m) || key.compareTo((Key) h.children[j + 1].key) < 0){
                    Node u = insert(h.children[j++].next, key, value, ht - 1);
                    if(u == null) return null;
                    toAdd.key = u.children[0].key;
                    toAdd.next = u;
                    break;
                }
            }
        }
        //shift the larger nodes right
        for(int i = h.m; i > j; i--) h.children[i] = h.children[i - 1];
        h.children[j] = toAdd;
        h.m++;
        if(h.m < M) return null;
        else return split(h);
    }
    private Node split(Node h){
        Node t = new Node(M / 2);
        h.m = M / 2;
        for(int j = 0; j < M / 2; j++){
            t.children[j] = h.children[M / 2 + j];
        }
        return t;
    }

    public Value delete(Key key){
        return (Value) delete(root, key, HT).value;
    }
    private Entry delete(Node h, Key key, int ht){
        Entry[] children = h.children;
        int j = 0;
        if(ht == 0){
            for(; j < h.m; j++){
                if(children[j].key.equals(key)){
                    break;
                }
            }
        }else {
            for(;j < h.m; j++){
                if(j + 1 == h.m || key.compareTo((Key) children[j + 1].key) < 0){
                    Entry deleted = delete(children[j].next, key, ht - 1);
                    if(children[j].next.m < M / 2){
                        children[j].next = combine(children[j - 1].next, children[j].next);
                        if(children[j].next.m == 0)
                            break;
                    }
                    return deleted;
                }
            }
        }
        Entry toReturn = children[j];
        for(int i = j; i < h.m; i++){
            children[i] = children[i + 1];
        }
        h.m--;
        N--;
        //if(h.m == 0)
            //h = null;
        return toReturn;
    }
    private Node combine(Node a, Node b){
        int size = a.m;
        for (int i = size; i < size + b.m; i++){
            a.children[i] = b.children[i - b.m];
            a.m++;
        }
        if(a.m < M)
            b.m = 0;
        else
            b = split(a);
        return b;
    }
    public String toString(){
        return toString(root, HT, "") + "\n";
    }
    private String toString(Node h, int ht, String indent){
        String s = "";
        Entry[] children = h.children;
        if(ht == 0){
            for(int j = 0; j < h.m; j++){
                s += indent + children[j].key + "-" + children[j].value + " ";
            }
        } else{
            for(int j = 0; j < h.m; j++){
                System.out.println("curr node: " + children[j].key);
                s += indent + "\n(" + children[j].key + ")\n";
                s += toString(children[j].next, ht - 1, indent + "     ");
            }
        }
        return s;
    }
    public int size(){
        return N;
    }
    public int height(){
        return HT;
    }
}

非常感谢!

0 个答案:

没有答案