Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library index.b_plus_tree; | 5 library index.b_plus_tree; |
| 6 | 6 |
| 7 import 'dart:collection'; | |
| 8 | |
| 7 | 9 |
| 8 /** | 10 /** |
| 9 * A simple B+ tree (http://en.wikipedia.org/wiki/B+_tree) implementation. | 11 * A simple B+ tree (http://en.wikipedia.org/wiki/B+_tree) implementation. |
| 12 * | |
| 13 * [K] is the keys type. | |
| 14 * [V] is the values type. | |
| 15 * [N] is the type of node identifiers using by the [NodeManager]. | |
| 10 */ | 16 */ |
| 11 class BPlusTree<K, V> { | 17 class BPlusTree<K, V, N> { |
| 12 /** | 18 /** |
| 13 * The [Comparator] to compare keys. | 19 * The [Comparator] to compare keys. |
| 14 */ | 20 */ |
| 15 final Comparator<K> _comparator; | 21 final Comparator<K> _comparator; |
| 16 | 22 |
| 17 /** | 23 /** |
| 24 * The [NodeManager] to manage nodes. | |
| 25 */ | |
| 26 final NodeManager<K, V, N> _manager; | |
| 27 | |
| 28 /** | |
| 18 * The maximum number of keys in an index node. | 29 * The maximum number of keys in an index node. |
| 19 */ | 30 */ |
| 20 final int _maxIndexKeys; | 31 final int _maxIndexKeys; |
| 21 | 32 |
| 22 /** | 33 /** |
| 23 * The maximum number of keys in a leaf node. | 34 * The maximum number of keys in a leaf node. |
| 24 */ | 35 */ |
| 25 final int _maxLeafKeys; | 36 final int _maxLeafKeys; |
| 26 | 37 |
| 27 /** | 38 /** |
| 28 * The root node. | 39 * The root node. |
| 29 */ | 40 */ |
| 30 _Node<K, V> _root; | 41 _Node<K, V, N> _root; |
| 31 | 42 |
| 32 BPlusTree(this._maxIndexKeys, this._maxLeafKeys, this._comparator) { | 43 /** |
| 33 _root = new _LeafNode(_maxLeafKeys, _comparator); | 44 * Creates a new [BPlusTree] instance. |
| 45 */ | |
| 46 BPlusTree(this._maxIndexKeys, this._maxLeafKeys, this._comparator, | |
| 47 this._manager) { | |
| 48 _root = _newLeafNode(); | |
| 49 _writeLeafNode(_root); | |
| 34 } | 50 } |
| 35 | 51 |
| 36 /** | 52 /** |
| 37 * Returns the value for [key] or `null` if [key] is not in the tree. | 53 * Returns the value for [key] or `null` if [key] is not in the tree. |
| 38 */ | 54 */ |
| 39 V find(K key) { | 55 V find(K key) { |
| 40 return _root.find(key); | 56 return _root.find(key); |
| 41 } | 57 } |
| 42 | 58 |
| 43 /** | 59 /** |
| 44 * Associates the [key] with the given [value]. | 60 * Associates the [key] with the given [value]. |
| 45 * | 61 * |
| 46 * If the key was already in the tree, its associated value is changed. | 62 * If the key was already in the tree, its associated value is changed. |
| 47 * Otherwise the key-value pair is added to the tree. | 63 * Otherwise the key-value pair is added to the tree. |
| 48 */ | 64 */ |
| 49 void insert(K key, V value) { | 65 void insert(K key, V value) { |
| 50 _Split<K, V> result = _root.insert(key, value); | 66 _Split<K, N> result = _root.insert(key, value); |
| 51 if (result != null) { | 67 if (result != null) { |
| 52 _IndexNode<K, V> newRoot = new _IndexNode<K, V>(_maxIndexKeys, | 68 _IndexNode<K, V, N> newRoot = _newIndexNode(); |
| 53 _comparator); | |
| 54 newRoot.keys.add(result.key); | 69 newRoot.keys.add(result.key); |
| 55 newRoot.children.add(result.left); | 70 newRoot.children.add(result.left); |
| 56 newRoot.children.add(result.right); | 71 newRoot.children.add(result.right); |
| 57 _root = newRoot; | 72 _root = newRoot; |
| 73 _writeIndexNode(_root); | |
| 58 } | 74 } |
| 59 } | 75 } |
| 60 | 76 |
| 61 /** | 77 /** |
| 62 * Removes the association for the given [key]. | 78 * Removes the association for the given [key]. |
| 63 * | 79 * |
| 64 * Returns the value associated with [key] in the tree or `null` if [key] is | 80 * Returns the value associated with [key] in the tree or `null` if [key] is |
| 65 * not in the tree. | 81 * not in the tree. |
| 66 */ | 82 */ |
| 67 V remove(K key) { | 83 V remove(K key) { |
| 68 _Remove<K, V> result = _root.remove(key, null, null, null); | 84 _Remove<K, V> result = _root.remove(key, null, null, null); |
| 69 if (_root is _IndexNode<K, V>) { | 85 if (_root is _IndexNode<K, V, N>) { |
| 70 List<_Node<K, V>> children = (_root as _IndexNode<K, V>).children; | 86 List<N> children = (_root as _IndexNode<K, V, N>).children; |
| 71 if (children.length == 1) { | 87 if (children.length == 1) { |
| 72 _root = children[0]; | 88 _manager.delete(_root.id); |
| 89 _root = _readNode(children[0]); | |
| 73 } | 90 } |
| 74 } | 91 } |
| 75 return result.value; | 92 return result.value; |
| 76 } | 93 } |
| 77 | 94 |
| 78 /** | 95 /** |
| 79 * Writes a textual presentation of the tree into [buffer]. | 96 * Writes a textual presentation of the tree into [buffer]. |
| 80 */ | 97 */ |
| 81 void writeOn(StringBuffer buffer) { | 98 void writeOn(StringBuffer buffer) { |
| 82 _root.writeOn(buffer, ''); | 99 _root.writeOn(buffer, ''); |
| 83 } | 100 } |
| 101 | |
| 102 /** | |
| 103 * Creates a new [_IndexNode] instance. | |
| 104 */ | |
| 105 _IndexNode<K, V, N> _newIndexNode() { | |
| 106 N id = _manager.createIndex(); | |
| 107 return new _IndexNode<K, V, N>(this, id, _maxIndexKeys); | |
| 108 } | |
| 109 | |
| 110 /** | |
| 111 * Creates a new [_LeafNode] instance. | |
| 112 */ | |
| 113 _LeafNode<K, V, N> _newLeafNode() { | |
| 114 N id = _manager.createLeaf(); | |
| 115 return new _LeafNode<K, V, N>(this, id, _maxLeafKeys); | |
| 116 } | |
| 117 | |
| 118 /** | |
| 119 * Reads the [_IndexNode] with [id] from the manager. | |
| 120 */ | |
| 121 _IndexNode<K, V, N> _readIndexNode(N id) { | |
| 122 IndexNodeData<K, N> data = _manager.readIndex(id); | |
| 123 _IndexNode<K, V, N> node = new _IndexNode<K, V, N>(this, id, _maxIndexKeys); | |
| 124 node.keys.addAll(data.keys); | |
| 125 node.children.addAll(data.children); | |
| 126 return node; | |
| 127 } | |
| 128 | |
| 129 /** | |
| 130 * Reads the [_LeafNode] with [id] from the manager. | |
| 131 */ | |
| 132 _LeafNode<K, V, N> _readLeafNode(N id) { | |
| 133 _LeafNode<K, V, N> node = new _LeafNode<K, V, N>(this, id, _maxLeafKeys); | |
| 134 LeafNodeData<K, V> data = _manager.readLeaf(id); | |
| 135 node.keys.addAll(data.keys); | |
| 136 node.values.addAll(data.values); | |
| 137 return node; | |
| 138 } | |
| 139 | |
| 140 /** | |
| 141 * Reads the [_IndexNode] or [_LeafNode] with [id] from the manager. | |
| 142 */ | |
| 143 _Node<K, V, N> _readNode(N id) { | |
| 144 if (_manager.isIndex(id)) { | |
| 145 return _readIndexNode(id); | |
| 146 } else { | |
| 147 return _readLeafNode(id); | |
| 148 } | |
| 149 } | |
| 150 | |
| 151 /** | |
| 152 * Writes [node] into the manager. | |
| 153 */ | |
| 154 void _writeIndexNode(_IndexNode<K, V, N> node) { | |
| 155 _manager.writeIndex(node.id, new IndexNodeData(node.keys, node.children)); | |
| 156 } | |
| 157 | |
| 158 /** | |
| 159 * Writes [node] into the manager. | |
| 160 */ | |
| 161 void _writeLeafNode(_LeafNode<K, V, N> node) { | |
| 162 _manager.writeLeaf(node.id, new LeafNodeData(node.keys, node.values)); | |
| 163 } | |
| 164 } | |
| 165 | |
| 166 | |
| 167 /** | |
| 168 * A container with information about an index node. | |
| 169 */ | |
| 170 class IndexNodeData<K, N> { | |
| 171 final List<N> children; | |
| 172 final List<K> keys; | |
| 173 IndexNodeData(this.keys, this.children); | |
| 174 } | |
| 175 | |
| 176 | |
| 177 /** | |
| 178 * A container with information about a leaf node. | |
| 179 */ | |
| 180 class LeafNodeData<K, V> { | |
| 181 final List<K> keys; | |
| 182 final List<V> values; | |
| 183 LeafNodeData(this.keys, this.values); | |
| 184 } | |
| 185 | |
| 186 | |
| 187 /** | |
| 188 * An implementation of [NodeManager] that keeps node information in memory. | |
| 189 */ | |
| 190 class MemoryNodeManager<K, V> implements NodeManager<K, V, int> { | |
| 191 Map<int, IndexNodeData> _indexDataMap = new HashMap<int, IndexNodeData>(); | |
| 192 Map<int, LeafNodeData> _leafDataMap = new HashMap<int, LeafNodeData>(); | |
| 193 int _nextPageIndexId = 0; | |
| 194 int _nextPageLeafId = 1; | |
| 195 | |
| 196 @override | |
| 197 int createIndex() { | |
| 198 int id = _nextPageIndexId; | |
| 199 _nextPageIndexId += 2; | |
| 200 return id; | |
| 201 } | |
| 202 | |
| 203 @override | |
| 204 int createLeaf() { | |
| 205 int id = _nextPageLeafId; | |
| 206 _nextPageLeafId += 2; | |
| 207 return id; | |
| 208 } | |
| 209 | |
| 210 @override | |
| 211 void delete(int id) { | |
| 212 if (isIndex(id)) { | |
| 213 _indexDataMap.remove(id); | |
| 214 } else { | |
| 215 _leafDataMap.remove(id); | |
| 216 } | |
| 217 } | |
| 218 | |
| 219 @override | |
| 220 bool isIndex(int id) { | |
| 221 return id.isEven; | |
| 222 } | |
| 223 | |
| 224 @override | |
| 225 IndexNodeData<K, int> readIndex(int id) { | |
| 226 return _indexDataMap[id]; | |
| 227 } | |
| 228 | |
| 229 @override | |
| 230 LeafNodeData<K, V> readLeaf(int id) { | |
| 231 return _leafDataMap[id]; | |
| 232 } | |
| 233 | |
| 234 @override | |
| 235 void writeIndex(int id, IndexNodeData<K, V> data) { | |
| 236 _indexDataMap[id] = data; | |
| 237 } | |
| 238 | |
| 239 @override | |
| 240 void writeLeaf(int id, LeafNodeData<K, V> data) { | |
| 241 _leafDataMap[id] = data; | |
| 242 } | |
| 243 } | |
| 244 | |
| 245 | |
| 246 /** | |
| 247 * A manager that manages nodes. | |
| 248 */ | |
| 249 abstract class NodeManager<K, V, N> { | |
| 250 /** | |
| 251 * Generates an identifier for a new index node. | |
| 252 */ | |
| 253 N createIndex(); | |
| 254 | |
| 255 /** | |
| 256 * Generates an identifier for a new leaf node. | |
| 257 */ | |
| 258 N createLeaf(); | |
| 259 | |
| 260 /** | |
| 261 * Deletes the node with the given identifier. | |
| 262 */ | |
| 263 void delete(N id); | |
| 264 | |
| 265 /** | |
| 266 * Checks if the node with the given identifier is an index or a leaf node. | |
| 267 */ | |
| 268 bool isIndex(N id); | |
| 269 | |
| 270 /** | |
| 271 * Reads information about the index node with the given identifier. | |
| 272 */ | |
| 273 IndexNodeData<K, N> readIndex(N id); | |
| 274 | |
| 275 /** | |
| 276 * Reads information about the leaf node with the given identifier. | |
| 277 */ | |
| 278 LeafNodeData<K, V> readLeaf(N id); | |
| 279 | |
| 280 /** | |
| 281 * Writes information about the index node with the given identifier. | |
| 282 */ | |
| 283 void writeIndex(N id, IndexNodeData<K, V> data); | |
| 284 | |
| 285 /** | |
| 286 * Writes information about the leaf node with the given identifier. | |
| 287 */ | |
| 288 void writeLeaf(N id, LeafNodeData<K, V> data); | |
| 84 } | 289 } |
| 85 | 290 |
| 86 | 291 |
| 87 /** | 292 /** |
| 88 * An index node with keys and children references. | 293 * An index node with keys and children references. |
| 89 */ | 294 */ |
| 90 class _IndexNode<K, V> extends _Node<K, V> { | 295 class _IndexNode<K, V, N> extends _Node<K, V, N> { |
|
Brian Wilkerson
2014/06/08 16:50:06
Should "_IndexNode" be renamed (in a separate CL)
| |
| 91 final List<_Node<K, V>> children = new List<_Node<K, V>>(); | 296 final List<N> children = new List<N>(); |
| 92 final int maxKeys; | 297 final int maxKeys; |
| 93 final int minKeys; | 298 final int minKeys; |
| 94 | 299 |
| 95 _IndexNode(int maxKeys, Comparator<K> comparator) | 300 _IndexNode(BPlusTree<K, V, N> tree, N id, int maxKeys) |
| 96 : super(comparator), | 301 : super(tree, id), |
| 97 maxKeys = maxKeys, | 302 maxKeys = maxKeys, |
| 98 minKeys = maxKeys ~/ 2; | 303 minKeys = maxKeys ~/ 2; |
| 99 | 304 |
| 100 @override | 305 @override |
| 101 V find(K key) { | 306 V find(K key) { |
| 102 int index = findChildIndex(key); | 307 int index = _findChildIndex(key); |
| 103 return children[index].find(key); | 308 _Node<K, V, N> child = tree._readNode(children[index]); |
| 104 } | 309 return child.find(key); |
| 105 | 310 } |
| 106 /** | 311 |
| 107 * Returns the index of the child into which [key] should be inserted. | 312 _Split<K, N> insert(K key, V value) { |
| 108 */ | |
| 109 int findChildIndex(K key) { | |
| 110 for (int i = 0; i < keys.length; i++) { | |
| 111 if (comparator(keys[i], key) > 0) { | |
| 112 return i; | |
| 113 } | |
| 114 } | |
| 115 return keys.length; | |
| 116 } | |
| 117 | |
| 118 _Split<K, V> insert(K key, V value) { | |
| 119 // Early split. | 313 // Early split. |
| 120 if (keys.length == maxKeys) { | 314 if (keys.length == maxKeys) { |
| 121 int middle = (maxKeys + 1) ~/ 2; | 315 int middle = (maxKeys + 1) ~/ 2; |
| 122 K splitKey = keys[middle]; | 316 K splitKey = keys[middle]; |
| 123 _IndexNode<K, V> sibling = new _IndexNode<K, V>(maxKeys, comparator); | 317 // Overflow into a new sibling. |
| 318 _IndexNode<K, V, N> sibling = tree._newIndexNode(); | |
| 124 sibling.keys.addAll(keys.getRange(middle + 1, keys.length)); | 319 sibling.keys.addAll(keys.getRange(middle + 1, keys.length)); |
| 125 sibling.children.addAll(children.getRange(middle + 1, children.length)); | 320 sibling.children.addAll(children.getRange(middle + 1, children.length)); |
| 126 keys.length = middle; | 321 keys.length = middle; |
| 127 children.length = middle + 1; | 322 children.length = middle + 1; |
| 323 // Insert into this node or sibling. | |
| 324 if (comparator(key, splitKey) < 0) { | |
| 325 _insertNotFull(key, value); | |
| 326 } else { | |
| 327 sibling._insertNotFull(key, value); | |
| 328 } | |
| 128 // Prepare split. | 329 // Prepare split. |
| 129 _Split<K, V> result = new _Split<K, V>(splitKey, this, sibling); | 330 tree._writeIndexNode(this); |
| 130 if (comparator(key, result.key) < 0) { | 331 tree._writeIndexNode(sibling); |
| 131 insertNotFull(key, value); | 332 return new _Split<K, N>(splitKey, id, sibling.id); |
| 132 } else { | |
| 133 sibling.insertNotFull(key, value); | |
| 134 } | |
| 135 return result; | |
| 136 } | 333 } |
| 137 // No split. | 334 // No split. |
| 138 insertNotFull(key, value); | 335 _insertNotFull(key, value); |
| 139 return null; | 336 return null; |
| 140 } | 337 } |
| 141 | 338 |
| 142 void insertNotFull(K key, V value) { | 339 @override |
| 143 int index = findChildIndex(key); | 340 _Remove<K, V> remove(K key, _Node<K, V, N> left, K anchor, _Node<K, V, |
| 144 _Split<K, V> result = children[index].insert(key, value); | 341 N> right) { |
| 145 if (result != null) { | 342 int index = _findChildIndex(key); |
| 146 keys.insert(index, result.key); | |
| 147 children[index] = result.left; | |
| 148 children.insert(index + 1, result.right); | |
| 149 } | |
| 150 } | |
| 151 | |
| 152 @override | |
| 153 _Remove<K, V> remove(K key, _Node<K, V> left, K anchor, _Node<K, V> right) { | |
| 154 int index = findChildIndex(key); | |
| 155 K thisAnchor = index == 0 ? keys[0] : keys[index - 1]; | 343 K thisAnchor = index == 0 ? keys[0] : keys[index - 1]; |
| 156 _Node<K, V> child = children[index]; | 344 // Prepare children. |
| 157 bool hasLeft = index != 0; | 345 _Node<K, V, N> child = tree._readNode(children[index]); |
| 158 bool hasRight = index < children.length - 1; | 346 _Node<K, V, N> leftChild; |
| 159 _Node<K, V> leftChild = hasLeft ? children[index - 1] : null; | 347 _Node<K, V, N> rightChild; |
| 160 _Node<K, V> rightChild = hasRight ? children[index + 1] : null; | 348 if (index != 0) { |
| 349 leftChild = tree._readNode(children[index - 1]); | |
| 350 } else { | |
| 351 leftChild = null; | |
| 352 } | |
| 353 if (index < children.length - 1) { | |
| 354 rightChild = tree._readNode(children[index + 1]); | |
| 355 } else { | |
| 356 rightChild = null; | |
| 357 } | |
| 161 // Ask child to remove. | 358 // Ask child to remove. |
| 162 _Remove<K, V> result = child.remove(key, leftChild, thisAnchor, rightChild); | 359 _Remove<K, V> result = child.remove(key, leftChild, thisAnchor, rightChild); |
| 163 V value = result.value; | 360 V value = result.value; |
| 164 if (value == null) { | 361 if (value == null) { |
| 165 return new _Remove<K, V>(value); | 362 return new _Remove<K, V>(value); |
| 166 } | 363 } |
| 167 // Update anchor if borrowed. | 364 // Do keys / children updates |
| 168 if (result.leftAnchor != null) { | 365 bool hasUpdates = false; |
| 169 keys[index - 1] = result.leftAnchor; | 366 { |
| 170 } | 367 // Update anchor if borrowed. |
| 171 if (result.rightAnchor != null) { | 368 if (result.leftAnchor != null) { |
| 172 keys[index] = result.rightAnchor; | 369 keys[index - 1] = result.leftAnchor; |
| 173 } | 370 hasUpdates = true; |
| 174 // Update keys / children if merged. | 371 } |
| 175 if (result.mergedLeft) { | 372 if (result.rightAnchor != null) { |
| 176 keys.removeAt(index - 1); | 373 keys[index] = result.rightAnchor; |
| 177 children.removeAt(index); | 374 hasUpdates = true; |
| 178 } | 375 } |
| 179 if (result.mergedRight) { | 376 // Update keys / children if merged. |
| 180 keys.removeAt(index); | 377 if (result.mergedLeft) { |
| 181 children.removeAt(index); | 378 keys.removeAt(index - 1); |
| 182 } | 379 N child = children.removeAt(index); |
| 380 manager.delete(child); | |
| 381 hasUpdates = true; | |
| 382 } | |
| 383 if (result.mergedRight) { | |
| 384 keys.removeAt(index); | |
| 385 N child = children.removeAt(index); | |
| 386 manager.delete(child); | |
| 387 hasUpdates = true; | |
| 388 } | |
| 389 } | |
| 390 // Write if updated. | |
| 391 if (!hasUpdates) { | |
| 392 return new _Remove<K, V>(value); | |
| 393 } | |
| 394 tree._writeIndexNode(this); | |
| 183 // Perform balancing. | 395 // Perform balancing. |
| 184 if (keys.length < minKeys) { | 396 if (keys.length < minKeys) { |
| 185 // Try left sibling. | 397 // Try left sibling. |
| 186 if (left is _IndexNode<K, V>) { | 398 if (left is _IndexNode<K, V, N>) { |
| 187 // Try to redistribute. | 399 // Try to redistribute. |
| 188 int leftLength = left.keys.length; | 400 int leftLength = left.keys.length; |
| 189 if (leftLength > minKeys) { | 401 if (leftLength > minKeys) { |
| 190 int halfExcess = (leftLength - minKeys + 1) ~/ 2; | 402 int halfExcess = (leftLength - minKeys + 1) ~/ 2; |
| 191 int newLeftLength = leftLength - halfExcess; | 403 int newLeftLength = leftLength - halfExcess; |
| 192 keys.insert(0, anchor); | 404 keys.insert(0, anchor); |
| 193 keys.insertAll(0, left.keys.getRange(newLeftLength, leftLength)); | 405 keys.insertAll(0, left.keys.getRange(newLeftLength, leftLength)); |
| 194 children.insertAll(0, left.children.getRange(newLeftLength, leftLength | 406 children.insertAll(0, left.children.getRange(newLeftLength, leftLength |
| 195 + 1)); | 407 + 1)); |
| 196 K newAnchor = left.keys[newLeftLength - 1]; | 408 K newAnchor = left.keys[newLeftLength - 1]; |
| 197 left.keys.length = newLeftLength - 1; | 409 left.keys.length = newLeftLength - 1; |
| 198 left.children.length = newLeftLength; | 410 left.children.length = newLeftLength; |
| 411 tree._writeIndexNode(this); | |
| 412 tree._writeIndexNode(left); | |
| 199 return new _Remove<K, V>.borrowLeft(value, newAnchor); | 413 return new _Remove<K, V>.borrowLeft(value, newAnchor); |
| 200 } | 414 } |
| 201 // Do merge. | 415 // Do merge. |
| 202 left.keys.add(anchor); | 416 left.keys.add(anchor); |
| 203 left.keys.addAll(keys); | 417 left.keys.addAll(keys); |
| 204 left.children.addAll(children); | 418 left.children.addAll(children); |
| 419 tree._writeIndexNode(this); | |
| 420 tree._writeIndexNode(left); | |
| 205 return new _Remove<K, V>.mergeLeft(value); | 421 return new _Remove<K, V>.mergeLeft(value); |
| 206 } | 422 } |
| 207 // Try right sibling. | 423 // Try right sibling. |
| 208 if (right is _IndexNode<K, V>) { | 424 if (right is _IndexNode<K, V, N>) { |
| 209 // Try to redistribute. | 425 // Try to redistribute. |
| 210 var rightLength = right.keys.length; | 426 var rightLength = right.keys.length; |
| 211 if (rightLength > minKeys) { | 427 if (rightLength > minKeys) { |
| 212 int halfExcess = (rightLength - minKeys + 1) ~/ 2; | 428 int halfExcess = (rightLength - minKeys + 1) ~/ 2; |
| 213 keys.add(anchor); | 429 keys.add(anchor); |
| 214 keys.addAll(right.keys.getRange(0, halfExcess - 1)); | 430 keys.addAll(right.keys.getRange(0, halfExcess - 1)); |
| 215 children.addAll(right.children.getRange(0, halfExcess)); | 431 children.addAll(right.children.getRange(0, halfExcess)); |
| 216 K newAnchor = right.keys[halfExcess - 1]; | 432 K newAnchor = right.keys[halfExcess - 1]; |
| 217 right.keys.removeRange(0, halfExcess); | 433 right.keys.removeRange(0, halfExcess); |
| 218 right.children.removeRange(0, halfExcess); | 434 right.children.removeRange(0, halfExcess); |
| 435 tree._writeIndexNode(this); | |
| 436 tree._writeIndexNode(right); | |
| 219 return new _Remove<K, V>.borrowRight(value, newAnchor); | 437 return new _Remove<K, V>.borrowRight(value, newAnchor); |
| 220 } | 438 } |
| 221 // Do merge. | 439 // Do merge. |
| 222 right.keys.insert(0, anchor); | 440 right.keys.insert(0, anchor); |
| 223 right.keys.insertAll(0, keys); | 441 right.keys.insertAll(0, keys); |
| 224 right.children.insertAll(0, children); | 442 right.children.insertAll(0, children); |
| 443 tree._writeIndexNode(this); | |
| 444 tree._writeIndexNode(right); | |
| 225 return new _Remove<K, V>.mergeRight(value); | 445 return new _Remove<K, V>.mergeRight(value); |
| 226 } | 446 } |
| 227 } | 447 } |
| 228 // No balancing required. | 448 // No balancing required. |
| 229 return new _Remove<K, V>(value); | 449 return new _Remove<K, V>(value); |
| 230 } | 450 } |
| 231 | 451 |
| 232 @override | 452 @override |
| 233 void writeOn(StringBuffer buffer, String indent) { | 453 void writeOn(StringBuffer buffer, String indent) { |
| 234 buffer.write(indent); | 454 buffer.write(indent); |
| 235 buffer.write('INode {\n'); | 455 buffer.write('INode {\n'); |
| 236 for (int i = 0; i < keys.length; i++) { | 456 for (int i = 0; i < keys.length; i++) { |
| 237 children[i].writeOn(buffer, indent + ' '); | 457 _Node<K, V, N> child = tree._readNode(children[i]); |
| 458 child.writeOn(buffer, indent + ' '); | |
| 238 buffer.write(indent); | 459 buffer.write(indent); |
| 239 buffer.write(' '); | 460 buffer.write(' '); |
| 240 buffer.write(keys[i]); | 461 buffer.write(keys[i]); |
| 241 buffer.write('\n'); | 462 buffer.write('\n'); |
| 242 } | 463 } |
| 243 children[keys.length].writeOn(buffer, indent + ' '); | 464 _Node<K, V, N> child = tree._readNode(children[keys.length]); |
| 465 child.writeOn(buffer, indent + ' '); | |
| 244 buffer.write(indent); | 466 buffer.write(indent); |
| 245 buffer.write('}\n'); | 467 buffer.write('}\n'); |
| 246 } | 468 } |
| 469 | |
| 470 /** | |
| 471 * Returns the index of the child into which [key] should be inserted. | |
| 472 */ | |
| 473 int _findChildIndex(K key) { | |
| 474 for (int i = 0; i < keys.length; i++) { | |
| 475 if (comparator(keys[i], key) > 0) { | |
| 476 return i; | |
| 477 } | |
| 478 } | |
| 479 return keys.length; | |
| 480 } | |
| 481 | |
| 482 void _insertNotFull(K key, V value) { | |
| 483 int index = _findChildIndex(key); | |
| 484 _Node<K, V, N> child = tree._readNode(children[index]); | |
| 485 _Split<K, N> result = child.insert(key, value); | |
| 486 if (result != null) { | |
| 487 keys.insert(index, result.key); | |
| 488 children[index] = result.left; | |
| 489 children.insert(index + 1, result.right); | |
| 490 tree._writeIndexNode(this); | |
| 491 } | |
| 492 } | |
| 247 } | 493 } |
| 248 | 494 |
| 249 | 495 |
| 250 /** | 496 /** |
| 251 * A leaf node with keys and values. | 497 * A leaf node with keys and values. |
| 252 */ | 498 */ |
| 253 class _LeafNode<K, V> extends _Node<K, V> { | 499 class _LeafNode<K, V, N> extends _Node<K, V, N> { |
| 254 final int maxKeys; | 500 final int maxKeys; |
| 255 final int minKeys; | 501 final int minKeys; |
| 256 | |
| 257 /** | |
| 258 * The list of values. | |
| 259 */ | |
| 260 final List<V> values = new List<V>(); | 502 final List<V> values = new List<V>(); |
| 261 | 503 |
| 262 _LeafNode(int maxKeys, Comparator<K> comparator) | 504 _LeafNode(BPlusTree<K, V, N> tree, N id, int maxKeys) |
| 263 : super(comparator), | 505 : super(tree, id), |
| 264 maxKeys = maxKeys, | 506 maxKeys = maxKeys, |
| 265 minKeys = maxKeys ~/ 2; | 507 minKeys = maxKeys ~/ 2; |
| 266 | 508 |
| 267 @override | 509 @override |
| 268 V find(K key) { | 510 V find(K key) { |
| 269 int index = findKeyIndex(key); | 511 int index = _findKeyIndex(key); |
| 270 if (index < 0) { | 512 if (index < 0) { |
| 271 return null; | 513 return null; |
| 272 } | 514 } |
| 273 if (index >= keys.length) { | 515 if (index >= keys.length) { |
| 274 return null; | 516 return null; |
| 275 } | 517 } |
| 276 if (keys[index] != key) { | 518 if (keys[index] != key) { |
| 277 return null; | 519 return null; |
| 278 } | 520 } |
| 279 return values[index]; | 521 return values[index]; |
| 280 } | 522 } |
| 281 | 523 |
| 282 /** | 524 _Split<K, N> insert(K key, V value) { |
| 283 * Returns the index where [key] should be inserted. | 525 int index = _findKeyIndex(key); |
| 284 */ | |
| 285 int findKeyIndex(K key) { | |
| 286 for (int i = 0; i < keys.length; i++) { | |
| 287 if (comparator(keys[i], key) >= 0) { | |
| 288 return i; | |
| 289 } | |
| 290 } | |
| 291 return keys.length; | |
| 292 } | |
| 293 | |
| 294 _Split<K, V> insert(K key, V value) { | |
| 295 int index = findKeyIndex(key); | |
| 296 // The node is full. | 526 // The node is full. |
| 297 if (keys.length == maxKeys) { | 527 if (keys.length == maxKeys) { |
| 298 int middle = (maxKeys + 1) ~/ 2; | 528 int middle = (maxKeys + 1) ~/ 2; |
| 299 _LeafNode<K, V> sibling = new _LeafNode<K, V>(maxKeys, comparator); | 529 _LeafNode<K, V, N> sibling = tree._newLeafNode(); |
| 300 sibling.keys.addAll(keys.getRange(middle, keys.length)); | 530 sibling.keys.addAll(keys.getRange(middle, keys.length)); |
| 301 sibling.values.addAll(values.getRange(middle, values.length)); | 531 sibling.values.addAll(values.getRange(middle, values.length)); |
| 302 keys.length = middle; | 532 keys.length = middle; |
| 303 values.length = middle; | 533 values.length = middle; |
| 304 // Insert into the left / right sibling. | 534 // Insert into the left / right sibling. |
| 305 if (index < middle) { | 535 if (index < middle) { |
| 306 insertNotFull(key, value, index); | 536 _insertNotFull(key, value, index); |
| 307 } else { | 537 } else { |
| 308 sibling.insertNotFull(key, value, index - middle); | 538 sibling._insertNotFull(key, value, index - middle); |
| 309 } | 539 } |
| 310 // Notify the parent about the split. | 540 // Notify the parent about the split. |
| 311 return new _Split<K, V>(sibling.keys[0], this, sibling); | 541 tree._writeLeafNode(this); |
| 542 tree._writeLeafNode(sibling); | |
| 543 return new _Split<K, N>(sibling.keys[0], id, sibling.id); | |
| 312 } | 544 } |
| 313 // The node was not full. | 545 // The node was not full. |
| 314 insertNotFull(key, value, index); | 546 _insertNotFull(key, value, index); |
| 315 return null; | 547 return null; |
| 316 } | 548 } |
| 317 | 549 |
| 318 void insertNotFull(K key, V value, int index) { | |
| 319 if (index < keys.length && keys[index] == key) { | |
| 320 values[index] = value; | |
| 321 } else { | |
| 322 keys.insert(index, key); | |
| 323 values.insert(index, value); | |
| 324 } | |
| 325 } | |
| 326 | |
| 327 @override | 550 @override |
| 328 _Remove<K, V> remove(K key, _Node<K, V> left, K anchor, _Node<K, V> right) { | 551 _Remove<K, V> remove(K key, _Node<K, V, N> left, K anchor, _Node<K, V, |
| 552 N> right) { | |
| 329 // Find the key. | 553 // Find the key. |
| 330 int index = keys.indexOf(key); | 554 int index = keys.indexOf(key); |
| 331 if (index == -1) { | 555 if (index == -1) { |
| 332 return new _Remove<K, V>(null); | 556 return new _Remove<K, V>(null); |
| 333 } | 557 } |
| 334 // Key key / value. | 558 // Remove key / value. |
| 335 keys.removeAt(index); | 559 keys.removeAt(index); |
| 336 V value = values.removeAt(index); | 560 V value = values.removeAt(index); |
| 561 tree._writeLeafNode(this); | |
| 337 // Perform balancing. | 562 // Perform balancing. |
| 338 if (keys.length < minKeys) { | 563 if (keys.length < minKeys) { |
| 339 // Try left sibling. | 564 // Try left sibling. |
| 340 if (left is _LeafNode<K, V>) { | 565 if (left is _LeafNode<K, V, N>) { |
| 341 // Try to redistribute. | 566 // Try to redistribute. |
| 342 int leftLength = left.keys.length; | 567 int leftLength = left.keys.length; |
| 343 if (leftLength > minKeys) { | 568 if (leftLength > minKeys) { |
| 344 int halfExcess = (leftLength - minKeys + 1) ~/ 2; | 569 int halfExcess = (leftLength - minKeys + 1) ~/ 2; |
| 345 int newLeftLength = leftLength - halfExcess; | 570 int newLeftLength = leftLength - halfExcess; |
| 346 keys.insertAll(0, left.keys.getRange(newLeftLength, leftLength)); | 571 keys.insertAll(0, left.keys.getRange(newLeftLength, leftLength)); |
| 347 values.insertAll(0, left.values.getRange(newLeftLength, leftLength)); | 572 values.insertAll(0, left.values.getRange(newLeftLength, |
| 573 leftLength)); | |
| 348 left.keys.length = newLeftLength; | 574 left.keys.length = newLeftLength; |
| 349 left.values.length = newLeftLength; | 575 left.values.length = newLeftLength; |
| 576 tree._writeLeafNode(this); | |
| 577 tree._writeLeafNode(left); | |
| 350 return new _Remove<K, V>.borrowLeft(value, keys.first); | 578 return new _Remove<K, V>.borrowLeft(value, keys.first); |
| 351 } | 579 } |
| 352 // Do merge. | 580 // Do merge. |
| 353 left.keys.addAll(keys); | 581 left.keys.addAll(keys); |
| 354 left.values.addAll(values); | 582 left.values.addAll(values); |
| 583 tree._writeLeafNode(this); | |
| 584 tree._writeLeafNode(left); | |
| 355 return new _Remove<K, V>.mergeLeft(value); | 585 return new _Remove<K, V>.mergeLeft(value); |
| 356 } | 586 } |
| 357 // Try right sibling. | 587 // Try right sibling. |
| 358 if (right is _LeafNode<K, V>) { | 588 if (right is _LeafNode<K, V, N>) { |
| 359 // Try to redistribute. | 589 // Try to redistribute. |
| 360 var rightLength = right.keys.length; | 590 var rightLength = right.keys.length; |
| 361 if (rightLength > minKeys) { | 591 if (rightLength > minKeys) { |
| 362 int halfExcess = (rightLength - minKeys + 1) ~/ 2; | 592 int halfExcess = (rightLength - minKeys + 1) ~/ 2; |
| 363 keys.addAll(right.keys.getRange(0, halfExcess)); | 593 keys.addAll(right.keys.getRange(0, halfExcess)); |
| 364 values.addAll(right.values.getRange(0, halfExcess)); | 594 values.addAll(right.values.getRange(0, halfExcess)); |
| 365 right.keys.removeRange(0, halfExcess); | 595 right.keys.removeRange(0, halfExcess); |
| 366 right.values.removeRange(0, halfExcess); | 596 right.values.removeRange(0, halfExcess); |
| 597 tree._writeLeafNode(this); | |
| 598 tree._writeLeafNode(right); | |
| 367 return new _Remove<K, V>.borrowRight(value, right.keys.first); | 599 return new _Remove<K, V>.borrowRight(value, right.keys.first); |
| 368 } | 600 } |
| 369 // Do merge. | 601 // Do merge. |
| 370 right.keys.insertAll(0, keys); | 602 right.keys.insertAll(0, keys); |
| 371 right.values.insertAll(0, values); | 603 right.values.insertAll(0, values); |
| 604 tree._writeLeafNode(this); | |
| 605 tree._writeLeafNode(right); | |
| 372 return new _Remove<K, V>.mergeRight(value); | 606 return new _Remove<K, V>.mergeRight(value); |
| 373 } | 607 } |
| 374 } | 608 } |
| 375 // No balancing required. | 609 // No balancing required. |
| 376 return new _Remove<K, V>(value); | 610 return new _Remove<K, V>(value); |
| 377 } | 611 } |
| 378 | 612 |
| 379 @override | 613 @override |
| 380 void writeOn(StringBuffer buffer, String indent) { | 614 void writeOn(StringBuffer buffer, String indent) { |
| 381 buffer.write(indent); | 615 buffer.write(indent); |
| 382 buffer.write('LNode {'); | 616 buffer.write('LNode {'); |
| 383 for (int i = 0; i < keys.length; i++) { | 617 for (int i = 0; i < keys.length; i++) { |
| 384 if (i != 0) { | 618 if (i != 0) { |
| 385 buffer.write(', '); | 619 buffer.write(', '); |
| 386 } | 620 } |
| 387 buffer.write(keys[i]); | 621 buffer.write(keys[i]); |
| 388 buffer.write(': '); | 622 buffer.write(': '); |
| 389 buffer.write(values[i]); | 623 buffer.write(values[i]); |
| 390 } | 624 } |
| 391 buffer.write('}\n'); | 625 buffer.write('}\n'); |
| 392 } | 626 } |
| 627 | |
| 628 /** | |
| 629 * Returns the index where [key] should be inserted. | |
| 630 */ | |
| 631 int _findKeyIndex(K key) { | |
| 632 for (int i = 0; i < keys.length; i++) { | |
| 633 if (comparator(keys[i], key) >= 0) { | |
| 634 return i; | |
| 635 } | |
| 636 } | |
| 637 return keys.length; | |
| 638 } | |
| 639 | |
| 640 void _insertNotFull(K key, V value, int index) { | |
| 641 if (index < keys.length && keys[index] == key) { | |
| 642 values[index] = value; | |
| 643 } else { | |
| 644 keys.insert(index, key); | |
| 645 values.insert(index, value); | |
| 646 } | |
| 647 tree._writeLeafNode(this); | |
| 648 } | |
| 393 } | 649 } |
| 394 | 650 |
| 395 | 651 |
| 396 /** | 652 /** |
| 397 * An internal or leaf node. | 653 * An internal or leaf node. |
| 398 */ | 654 */ |
| 399 abstract class _Node<K, V> { | 655 abstract class _Node<K, V, N> { |
| 400 /** | 656 /** |
| 401 * The [Comparator] to compare keys. | 657 * The [Comparator] to compare keys. |
| 402 */ | 658 */ |
| 403 Comparator<K> comparator; | 659 final Comparator<K> comparator; |
| 660 | |
| 661 /** | |
| 662 * The identifier of this node. | |
| 663 */ | |
| 664 final N id; | |
| 404 | 665 |
| 405 /** | 666 /** |
| 406 * The list of keys. | 667 * The list of keys. |
| 407 */ | 668 */ |
| 408 List<K> keys = new List<K>(); | 669 final List<K> keys = new List<K>(); |
| 409 | 670 |
| 410 _Node(this.comparator); | 671 /** |
| 672 * The [NodeManager] for this tree. | |
| 673 */ | |
| 674 final NodeManager<K, V, N> manager; | |
| 675 | |
| 676 /** | |
| 677 * The [BPlusTree] this node belongs to. | |
| 678 */ | |
| 679 final BPlusTree<K, V, N> tree; | |
| 680 | |
| 681 _Node(BPlusTree<K, V, N> tree, this.id) | |
| 682 : tree = tree, | |
| 683 comparator = tree._comparator, | |
| 684 manager = tree._manager; | |
| 411 | 685 |
| 412 /** | 686 /** |
| 413 * Looks for [key]. | 687 * Looks for [key]. |
| 414 * | 688 * |
| 415 * Returns the associated value if found. | 689 * Returns the associated value if found. |
| 416 * Returns `null` if not found. | 690 * Returns `null` if not found. |
| 417 */ | 691 */ |
| 418 V find(K key); | 692 V find(K key); |
| 419 | 693 |
| 420 /** | 694 /** |
| 421 * Inserts the [key] / [value] pair into this [_Node]. | 695 * Inserts the [key] / [value] pair into this [_Node]. |
| 422 * | 696 * |
| 423 * Returns a [_Split] object if split happens, or `null` otherwise. | 697 * Returns a [_Split] object if split happens, or `null` otherwise. |
| 424 */ | 698 */ |
| 425 _Split<K, V> insert(K key, V value); | 699 _Split<K, N> insert(K key, V value); |
| 426 | 700 |
| 427 /** | 701 /** |
| 428 * Removes the association for the given [key]. | 702 * Removes the association for the given [key]. |
| 429 * | 703 * |
| 430 * Returns the [_Remove] information about an operation performed. | 704 * Returns the [_Remove] information about an operation performed. |
| 431 * It may be restructuring or merging, with [left] or [left] siblings. | 705 * It may be restructuring or merging, with [left] or [left] siblings. |
| 432 */ | 706 */ |
| 433 _Remove<K, V> remove(K key, _Node<K, V> left, K anchor, _Node<K, V> right); | 707 _Remove<K, V> remove(K key, _Node<K, V, N> left, K anchor, _Node<K, V, |
| 708 N> right); | |
| 434 | 709 |
| 435 /** | 710 /** |
| 436 * Writes a textual presentation of the tree into [buffer]. | 711 * Writes a textual presentation of the tree into [buffer]. |
| 437 */ | 712 */ |
| 438 void writeOn(StringBuffer buffer, String indent); | 713 void writeOn(StringBuffer buffer, String indent); |
| 439 } | 714 } |
| 440 | 715 |
| 441 | 716 |
| 442 /** | 717 /** |
| 443 * A container with information about redistribute / merge. | 718 * A container with information about redistribute / merge. |
| 444 */ | 719 */ |
| 445 class _Remove<K, V> { | 720 class _Remove<K, V> { |
| 446 K leftAnchor; | 721 K leftAnchor; |
| 447 bool mergedLeft = false; | 722 bool mergedLeft = false; |
| 448 bool mergedRight = false; | 723 bool mergedRight = false; |
| 449 K rightAnchor; | 724 K rightAnchor; |
| 450 final V value; | 725 final V value; |
| 451 _Remove(this.value); | 726 _Remove(this.value); |
| 452 _Remove.borrowLeft(this.value, this.leftAnchor); | 727 _Remove.borrowLeft(this.value, this.leftAnchor); |
| 453 _Remove.borrowRight(this.value, this.rightAnchor); | 728 _Remove.borrowRight(this.value, this.rightAnchor); |
| 454 _Remove.mergeLeft(this.value) : mergedLeft = true; | 729 _Remove.mergeLeft(this.value) : mergedLeft = true; |
| 455 _Remove.mergeRight(this.value) : mergedRight = true; | 730 _Remove.mergeRight(this.value) : mergedRight = true; |
| 456 } | 731 } |
| 457 | 732 |
| 458 | 733 |
| 459 /** | 734 /** |
| 460 * A container with information about split during insert. | 735 * A container with information about split during insert. |
| 461 */ | 736 */ |
| 462 class _Split<K, V> { | 737 class _Split<K, N> { |
| 463 final K key; | 738 final K key; |
| 464 final _Node<K, V> left; | 739 final N left; |
| 465 final _Node<K, V> right; | 740 final N right; |
| 466 _Split(this.key, this.left, this.right); | 741 _Split(this.key, this.left, this.right); |
| 467 } | 742 } |
| OLD | NEW |