| 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'; | 7 import 'dart:collection'; |
| 8 | 8 |
| 9 | 9 |
| 10 /** | 10 /** |
| (...skipping 25 matching lines...) Expand all Loading... |
| 36 final int _maxLeafKeys; | 36 final int _maxLeafKeys; |
| 37 | 37 |
| 38 /** | 38 /** |
| 39 * The root node. | 39 * The root node. |
| 40 */ | 40 */ |
| 41 _Node<K, V, N> _root; | 41 _Node<K, V, N> _root; |
| 42 | 42 |
| 43 /** | 43 /** |
| 44 * Creates a new [BPlusTree] instance. | 44 * Creates a new [BPlusTree] instance. |
| 45 */ | 45 */ |
| 46 BPlusTree(this._maxIndexKeys, this._maxLeafKeys, this._comparator, | 46 BPlusTree(this._comparator, NodeManager<K, V, N> manager) |
| 47 this._manager) { | 47 : _manager = manager, |
| 48 _maxIndexKeys = manager.maxIndexKeys, |
| 49 _maxLeafKeys = manager.maxLeafKeys { |
| 48 _root = _newLeafNode(); | 50 _root = _newLeafNode(); |
| 49 _writeLeafNode(_root); | 51 _writeLeafNode(_root); |
| 50 } | 52 } |
| 51 | 53 |
| 52 /** | 54 /** |
| 53 * Returns the value for [key] or `null` if [key] is not in the tree. | 55 * Returns the value for [key] or `null` if [key] is not in the tree. |
| 54 */ | 56 */ |
| 55 V find(K key) { | 57 V find(K key) { |
| 56 return _root.find(key); | 58 return _root.find(key); |
| 57 } | 59 } |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 181 final List<K> keys; | 183 final List<K> keys; |
| 182 final List<V> values; | 184 final List<V> values; |
| 183 LeafNodeData(this.keys, this.values); | 185 LeafNodeData(this.keys, this.values); |
| 184 } | 186 } |
| 185 | 187 |
| 186 | 188 |
| 187 /** | 189 /** |
| 188 * An implementation of [NodeManager] that keeps node information in memory. | 190 * An implementation of [NodeManager] that keeps node information in memory. |
| 189 */ | 191 */ |
| 190 class MemoryNodeManager<K, V> implements NodeManager<K, V, int> { | 192 class MemoryNodeManager<K, V> implements NodeManager<K, V, int> { |
| 193 final int maxIndexKeys; |
| 194 final int maxLeafKeys; |
| 191 Map<int, IndexNodeData> _indexDataMap = new HashMap<int, IndexNodeData>(); | 195 Map<int, IndexNodeData> _indexDataMap = new HashMap<int, IndexNodeData>(); |
| 192 Map<int, LeafNodeData> _leafDataMap = new HashMap<int, LeafNodeData>(); | 196 Map<int, LeafNodeData> _leafDataMap = new HashMap<int, LeafNodeData>(); |
| 197 |
| 193 int _nextPageIndexId = 0; | 198 int _nextPageIndexId = 0; |
| 194 int _nextPageLeafId = 1; | 199 int _nextPageLeafId = 1; |
| 195 | 200 |
| 201 MemoryNodeManager(this.maxIndexKeys, this.maxLeafKeys); |
| 202 |
| 196 @override | 203 @override |
| 197 int createIndex() { | 204 int createIndex() { |
| 198 int id = _nextPageIndexId; | 205 int id = _nextPageIndexId; |
| 199 _nextPageIndexId += 2; | 206 _nextPageIndexId += 2; |
| 200 return id; | 207 return id; |
| 201 } | 208 } |
| 202 | 209 |
| 203 @override | 210 @override |
| 204 int createLeaf() { | 211 int createLeaf() { |
| 205 int id = _nextPageLeafId; | 212 int id = _nextPageLeafId; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 241 _leafDataMap[id] = data; | 248 _leafDataMap[id] = data; |
| 242 } | 249 } |
| 243 } | 250 } |
| 244 | 251 |
| 245 | 252 |
| 246 /** | 253 /** |
| 247 * A manager that manages nodes. | 254 * A manager that manages nodes. |
| 248 */ | 255 */ |
| 249 abstract class NodeManager<K, V, N> { | 256 abstract class NodeManager<K, V, N> { |
| 250 /** | 257 /** |
| 258 * The maximum number of keys in an index node. |
| 259 */ |
| 260 int get maxIndexKeys; |
| 261 |
| 262 /** |
| 263 * The maximum number of keys in a leaf node. |
| 264 */ |
| 265 int get maxLeafKeys; |
| 266 |
| 267 /** |
| 251 * Generates an identifier for a new index node. | 268 * Generates an identifier for a new index node. |
| 252 */ | 269 */ |
| 253 N createIndex(); | 270 N createIndex(); |
| 254 | 271 |
| 255 /** | 272 /** |
| 256 * Generates an identifier for a new leaf node. | 273 * Generates an identifier for a new leaf node. |
| 257 */ | 274 */ |
| 258 N createLeaf(); | 275 N createLeaf(); |
| 259 | 276 |
| 260 /** | 277 /** |
| (...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 562 // Perform balancing. | 579 // Perform balancing. |
| 563 if (keys.length < minKeys) { | 580 if (keys.length < minKeys) { |
| 564 // Try left sibling. | 581 // Try left sibling. |
| 565 if (left is _LeafNode<K, V, N>) { | 582 if (left is _LeafNode<K, V, N>) { |
| 566 // Try to redistribute. | 583 // Try to redistribute. |
| 567 int leftLength = left.keys.length; | 584 int leftLength = left.keys.length; |
| 568 if (leftLength > minKeys) { | 585 if (leftLength > minKeys) { |
| 569 int halfExcess = (leftLength - minKeys + 1) ~/ 2; | 586 int halfExcess = (leftLength - minKeys + 1) ~/ 2; |
| 570 int newLeftLength = leftLength - halfExcess; | 587 int newLeftLength = leftLength - halfExcess; |
| 571 keys.insertAll(0, left.keys.getRange(newLeftLength, leftLength)); | 588 keys.insertAll(0, left.keys.getRange(newLeftLength, leftLength)); |
| 572 values.insertAll(0, left.values.getRange(newLeftLength, | 589 values.insertAll(0, left.values.getRange(newLeftLength, leftLength)); |
| 573 leftLength)); | |
| 574 left.keys.length = newLeftLength; | 590 left.keys.length = newLeftLength; |
| 575 left.values.length = newLeftLength; | 591 left.values.length = newLeftLength; |
| 576 tree._writeLeafNode(this); | 592 tree._writeLeafNode(this); |
| 577 tree._writeLeafNode(left); | 593 tree._writeLeafNode(left); |
| 578 return new _Remove<K, V>.borrowLeft(value, keys.first); | 594 return new _Remove<K, V>.borrowLeft(value, keys.first); |
| 579 } | 595 } |
| 580 // Do merge. | 596 // Do merge. |
| 581 left.keys.addAll(keys); | 597 left.keys.addAll(keys); |
| 582 left.values.addAll(values); | 598 left.values.addAll(values); |
| 583 tree._writeLeafNode(this); | 599 tree._writeLeafNode(this); |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 733 | 749 |
| 734 /** | 750 /** |
| 735 * A container with information about split during insert. | 751 * A container with information about split during insert. |
| 736 */ | 752 */ |
| 737 class _Split<K, N> { | 753 class _Split<K, N> { |
| 738 final K key; | 754 final K key; |
| 739 final N left; | 755 final N left; |
| 740 final N right; | 756 final N right; |
| 741 _Split(this.key, this.left, this.right); | 757 _Split(this.key, this.left, this.right); |
| 742 } | 758 } |
| OLD | NEW |