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'; | 7 import 'dart:collection'; |
| 8 | 8 |
| 9 | 9 |
| 10 /** | 10 /** |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 116 N id = _manager.createLeaf(); | 116 N id = _manager.createLeaf(); |
| 117 return new _LeafNode<K, V, N>(this, id, _maxLeafKeys); | 117 return new _LeafNode<K, V, N>(this, id, _maxLeafKeys); |
| 118 } | 118 } |
| 119 | 119 |
| 120 /** | 120 /** |
| 121 * Reads the [_IndexNode] with [id] from the manager. | 121 * Reads the [_IndexNode] with [id] from the manager. |
| 122 */ | 122 */ |
| 123 _IndexNode<K, V, N> _readIndexNode(N id) { | 123 _IndexNode<K, V, N> _readIndexNode(N id) { |
| 124 IndexNodeData<K, N> data = _manager.readIndex(id); | 124 IndexNodeData<K, N> data = _manager.readIndex(id); |
| 125 _IndexNode<K, V, N> node = new _IndexNode<K, V, N>(this, id, _maxIndexKeys); | 125 _IndexNode<K, V, N> node = new _IndexNode<K, V, N>(this, id, _maxIndexKeys); |
| 126 node.keys.addAll(data.keys); | 126 node.keys = data.keys; |
| 127 node.children.addAll(data.children); | 127 node.children = data.children; |
| 128 return node; | 128 return node; |
| 129 } | 129 } |
| 130 | 130 |
| 131 /** | 131 /** |
| 132 * Reads the [_LeafNode] with [id] from the manager. | 132 * Reads the [_LeafNode] with [id] from the manager. |
| 133 */ | 133 */ |
| 134 _LeafNode<K, V, N> _readLeafNode(N id) { | 134 _LeafNode<K, V, N> _readLeafNode(N id) { |
| 135 _LeafNode<K, V, N> node = new _LeafNode<K, V, N>(this, id, _maxLeafKeys); | 135 _LeafNode<K, V, N> node = new _LeafNode<K, V, N>(this, id, _maxLeafKeys); |
| 136 LeafNodeData<K, V> data = _manager.readLeaf(id); | 136 LeafNodeData<K, V> data = _manager.readLeaf(id); |
| 137 node.keys.addAll(data.keys); | 137 node.keys = data.keys; |
| 138 node.values.addAll(data.values); | 138 node.values = data.values; |
| 139 return node; | 139 return node; |
| 140 } | 140 } |
| 141 | 141 |
| 142 /** | 142 /** |
| 143 * Reads the [_IndexNode] or [_LeafNode] with [id] from the manager. | 143 * Reads the [_IndexNode] or [_LeafNode] with [id] from the manager. |
| 144 */ | 144 */ |
| 145 _Node<K, V, N> _readNode(N id) { | 145 _Node<K, V, N> _readNode(N id) { |
| 146 if (_manager.isIndex(id)) { | 146 if (_manager.isIndex(id)) { |
| 147 return _readIndexNode(id); | 147 return _readIndexNode(id); |
| 148 } else { | 148 } else { |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 303 * Writes information about the leaf node with the given identifier. | 303 * Writes information about the leaf node with the given identifier. |
| 304 */ | 304 */ |
| 305 void writeLeaf(N id, LeafNodeData<K, V> data); | 305 void writeLeaf(N id, LeafNodeData<K, V> data); |
| 306 } | 306 } |
| 307 | 307 |
| 308 | 308 |
| 309 /** | 309 /** |
| 310 * An index node with keys and children references. | 310 * An index node with keys and children references. |
| 311 */ | 311 */ |
| 312 class _IndexNode<K, V, N> extends _Node<K, V, N> { | 312 class _IndexNode<K, V, N> extends _Node<K, V, N> { |
| 313 final List<N> children = new List<N>(); | 313 List<N> children = new List<N>(); |
| 314 final int maxKeys; | 314 final int maxKeys; |
| 315 final int minKeys; | 315 final int minKeys; |
| 316 | 316 |
| 317 _IndexNode(BPlusTree<K, V, N> tree, N id, int maxKeys) | 317 _IndexNode(BPlusTree<K, V, N> tree, N id, int maxKeys) |
| 318 : super(tree, id), | 318 : super(tree, id), |
| 319 maxKeys = maxKeys, | 319 maxKeys = maxKeys, |
| 320 minKeys = maxKeys ~/ 2; | 320 minKeys = maxKeys ~/ 2; |
| 321 | 321 |
| 322 @override | 322 @override |
| 323 V find(K key) { | 323 V find(K key) { |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 481 _Node<K, V, N> child = tree._readNode(children[keys.length]); | 481 _Node<K, V, N> child = tree._readNode(children[keys.length]); |
| 482 child.writeOn(buffer, indent + ' '); | 482 child.writeOn(buffer, indent + ' '); |
| 483 buffer.write(indent); | 483 buffer.write(indent); |
| 484 buffer.write('}\n'); | 484 buffer.write('}\n'); |
| 485 } | 485 } |
| 486 | 486 |
| 487 /** | 487 /** |
| 488 * Returns the index of the child into which [key] should be inserted. | 488 * Returns the index of the child into which [key] should be inserted. |
| 489 */ | 489 */ |
| 490 int _findChildIndex(K key) { | 490 int _findChildIndex(K key) { |
| 491 for (int i = 0; i < keys.length; i++) { | 491 int lo = 0; |
|
Brian Wilkerson
2014/06/10 17:08:29
Seems like a good candidate for a general utility
scheglov
2014/06/10 17:23:45
Yes, in general, but they are not completely ident
| |
| 492 if (comparator(keys[i], key) > 0) { | 492 int hi = keys.length - 1; |
| 493 return i; | 493 while (lo <= hi) { |
| 494 int mid = lo + (hi - lo) ~/ 2; | |
| 495 int compare = comparator(key, keys[mid]); | |
| 496 if (compare < 0) { | |
| 497 hi = mid - 1; | |
| 498 } else if (compare > 0) { | |
| 499 lo = mid + 1; | |
| 500 } else { | |
| 501 return mid + 1; | |
| 494 } | 502 } |
| 495 } | 503 } |
| 496 return keys.length; | 504 return lo; |
| 497 } | 505 } |
| 498 | 506 |
| 499 void _insertNotFull(K key, V value) { | 507 void _insertNotFull(K key, V value) { |
| 500 int index = _findChildIndex(key); | 508 int index = _findChildIndex(key); |
| 501 _Node<K, V, N> child = tree._readNode(children[index]); | 509 _Node<K, V, N> child = tree._readNode(children[index]); |
| 502 _Split<K, N> result = child.insert(key, value); | 510 _Split<K, N> result = child.insert(key, value); |
| 503 if (result != null) { | 511 if (result != null) { |
| 504 keys.insert(index, result.key); | 512 keys.insert(index, result.key); |
| 505 children[index] = result.left; | 513 children[index] = result.left; |
| 506 children.insert(index + 1, result.right); | 514 children.insert(index + 1, result.right); |
| 507 tree._writeIndexNode(this); | 515 tree._writeIndexNode(this); |
| 508 } | 516 } |
| 509 } | 517 } |
| 510 } | 518 } |
| 511 | 519 |
| 512 | 520 |
| 513 /** | 521 /** |
| 514 * A leaf node with keys and values. | 522 * A leaf node with keys and values. |
| 515 */ | 523 */ |
| 516 class _LeafNode<K, V, N> extends _Node<K, V, N> { | 524 class _LeafNode<K, V, N> extends _Node<K, V, N> { |
| 517 final int maxKeys; | 525 final int maxKeys; |
| 518 final int minKeys; | 526 final int minKeys; |
| 519 final List<V> values = new List<V>(); | 527 List<V> values = new List<V>(); |
| 520 | 528 |
| 521 _LeafNode(BPlusTree<K, V, N> tree, N id, int maxKeys) | 529 _LeafNode(BPlusTree<K, V, N> tree, N id, int maxKeys) |
| 522 : super(tree, id), | 530 : super(tree, id), |
| 523 maxKeys = maxKeys, | 531 maxKeys = maxKeys, |
| 524 minKeys = maxKeys ~/ 2; | 532 minKeys = maxKeys ~/ 2; |
| 525 | 533 |
| 526 @override | 534 @override |
| 527 V find(K key) { | 535 V find(K key) { |
| 528 int index = _findKeyIndex(key); | 536 int index = _findKeyIndex(key); |
| 529 if (index < 0) { | 537 if (index < 0) { |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 638 buffer.write(': '); | 646 buffer.write(': '); |
| 639 buffer.write(values[i]); | 647 buffer.write(values[i]); |
| 640 } | 648 } |
| 641 buffer.write('}\n'); | 649 buffer.write('}\n'); |
| 642 } | 650 } |
| 643 | 651 |
| 644 /** | 652 /** |
| 645 * Returns the index where [key] should be inserted. | 653 * Returns the index where [key] should be inserted. |
| 646 */ | 654 */ |
| 647 int _findKeyIndex(K key) { | 655 int _findKeyIndex(K key) { |
| 648 for (int i = 0; i < keys.length; i++) { | 656 int lo = 0; |
|
Brian Wilkerson
2014/06/10 17:08:29
Especially since it's already been duplicated. :-)
| |
| 649 if (comparator(keys[i], key) >= 0) { | 657 int hi = keys.length - 1; |
| 650 return i; | 658 while (lo <= hi) { |
| 659 int mid = lo + (hi - lo) ~/ 2; | |
| 660 int compare = comparator(key, keys[mid]); | |
| 661 if (compare < 0) { | |
| 662 hi = mid - 1; | |
| 663 } else if (compare > 0) { | |
| 664 lo = mid + 1; | |
| 665 } else { | |
| 666 return mid; | |
| 651 } | 667 } |
| 652 } | 668 } |
| 653 return keys.length; | 669 return lo; |
| 654 } | 670 } |
| 655 | 671 |
| 656 void _insertNotFull(K key, V value, int index) { | 672 void _insertNotFull(K key, V value, int index) { |
| 657 if (index < keys.length && keys[index] == key) { | 673 if (index < keys.length && keys[index] == key) { |
| 658 values[index] = value; | 674 values[index] = value; |
| 659 } else { | 675 } else { |
| 660 keys.insert(index, key); | 676 keys.insert(index, key); |
| 661 values.insert(index, value); | 677 values.insert(index, value); |
| 662 } | 678 } |
| 663 tree._writeLeafNode(this); | 679 tree._writeLeafNode(this); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 675 final Comparator<K> comparator; | 691 final Comparator<K> comparator; |
| 676 | 692 |
| 677 /** | 693 /** |
| 678 * The identifier of this node. | 694 * The identifier of this node. |
| 679 */ | 695 */ |
| 680 final N id; | 696 final N id; |
| 681 | 697 |
| 682 /** | 698 /** |
| 683 * The list of keys. | 699 * The list of keys. |
| 684 */ | 700 */ |
| 685 final List<K> keys = new List<K>(); | 701 List<K> keys = new List<K>(); |
| 686 | 702 |
| 687 /** | 703 /** |
| 688 * The [NodeManager] for this tree. | 704 * The [NodeManager] for this tree. |
| 689 */ | 705 */ |
| 690 final NodeManager<K, V, N> manager; | 706 final NodeManager<K, V, N> manager; |
| 691 | 707 |
| 692 /** | 708 /** |
| 693 * The [BPlusTree] this node belongs to. | 709 * The [BPlusTree] this node belongs to. |
| 694 */ | 710 */ |
| 695 final BPlusTree<K, V, N> tree; | 711 final BPlusTree<K, V, N> tree; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 749 | 765 |
| 750 /** | 766 /** |
| 751 * A container with information about split during insert. | 767 * A container with information about split during insert. |
| 752 */ | 768 */ |
| 753 class _Split<K, N> { | 769 class _Split<K, N> { |
| 754 final K key; | 770 final K key; |
| 755 final N left; | 771 final N left; |
| 756 final N right; | 772 final N right; |
| 757 _Split(this.key, this.left, this.right); | 773 _Split(this.key, this.left, this.right); |
| 758 } | 774 } |
| OLD | NEW |