我正在尝试实现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;
}
}
非常感谢!