-
Notifications
You must be signed in to change notification settings - Fork 3
/
LeafNode.java
130 lines (113 loc) · 3.82 KB
/
LeafNode.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/*
* File: LeafNode.java
* Description: An internal node in the BTree
* Author: Benjamin David Mayes <[email protected]>
*/
import java.lang.reflect.Array;
import java.util.Arrays;
/**
* A node that is a leaf of the BTree
*/
class LeafNode<K extends Comparable, V> extends Node<K,V> {
private V[] children;
/**
* Constructs a LeafNode with K as the key and parent as the parent.
*
* @param key The initial key in this node.
* @param parent The parent of this node.
*/
@SuppressWarnings({"unchecked"})
public LeafNode( K key, V value ) {
super(key);
children = (V[])(Array.newInstance( value.getClass(), numKeysPerNode + 2 ));
children[0] = value;
}
private LeafNode( K[] keys, V[] values, int numKeys, Node<K,V> parent, Node<K,V> next ) {
super( keys, numKeys, parent, next );
children = Utilities.copyOf( values, numKeysPerNode + 2);
}
/**
* Get the child of the given key.
*
* @param key The key to get the child of.
* @return A node in a Union or null.
*/
@SuppressWarnings({"unchecked"})
public Union.Right<Node<K,V>,V> getChild( K key ) {
int i = 0;
// The contents of the node are sorted, iterate while lexicographically less.
while( i < numKeys && keys[i].compareTo( key ) < 0 ) {
++i;
}
// check for equality
if( i < numKeysPerNode && keys[i] != null && keys[i].equals( key ) ) {
return new Union.Right<Node<K,V>,V>( children[i] );
}
else {
return new Union.Right<Node<K,V>,V>(null);
}
}
/**
* Adds a key:value pair to the current LeafNode.
* @param key The key of the value to add
* @param value The value of the key to add.
* @return True if success, false otherwise.
*/
@SuppressWarnings({"unchecked"})
public boolean addValue( K key, V value )
{
// we need to insert the key:value pair in order
int i = 0;
while( i < numKeys && keys[i].compareTo( key ) < 0 ) {
++i;
}
if( i != numKeys && keys[i].compareTo( key ) == 0 ) {
// we can replace the old value for this key
children[i] = value;
} else if( numKeys != numKeysPerNode) {
// we can add a new value if and only if there is room
// move everything over
for( int j = numKeys; j > i; --j ) {
keys[j] = keys[j-1];
children[j] = children[j-1];
}
// insert the key:value pair in the correct spot
keys[i] = key;
children[i] = value;
numKeys++;
} else {
return false;
}
return true;
}
/** {@inheritDoc} */
public Union.Right<InternalNode<K,V>,LeafNode<K,V>> split( K key, V value )
{
// Number of children of a leaf node is the same as the number
// of keys.
LeafNode<K,V> newNode = new LeafNode<K,V>(
Utilities.copyOfRange( this.keys, (numKeysPerNode)/2, numKeysPerNode ),
Utilities.copyOfRange( this.children, numKeysPerNode/2, numKeysPerNode ),
numKeysPerNode/2,
this.parent,
this.next );
this.next = newNode;
// Resize our key array
this.numKeys = numKeysPerNode/2;
if( key.compareTo( newNode.lowerBound() ) >= 0 ) {
newNode.addValue( key, value );
} else {
addValue( key, value );
}
return new Union.Right<InternalNode<K,V>,LeafNode<K,V>>(newNode);
}
public String toString()
{
String output = "[L";
for( int i = 0; i < numKeys; ++i )
{
output += " " + keys[i] + ":" + children[i] + ", ";
}
return output + "]";
}
}