Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(23)

Side by Side Diff: sdk/lib/collection/splay_tree.dart

Issue 61733013: Add SplayTreeSet. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Added more tests Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 part of dart.collection; 5 part of dart.collection;
6 6
7 typedef bool _Predicate<T>(T value); 7 typedef bool _Predicate<T>(T value);
8 8
9 /** 9 /**
10 * A node in a splay tree. It holds the sorting key and the left 10 * A node in a splay tree. It holds the sorting key and the left
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 current.right = _dummy.left; 130 current.right = _dummy.left;
131 _root = current; 131 _root = current;
132 132
133 _dummy.right = null; 133 _dummy.right = null;
134 _dummy.left = null; 134 _dummy.left = null;
135 _splayCount++; 135 _splayCount++;
136 return comp; 136 return comp;
137 } 137 }
138 138
139 // Emulates splaying with a key that is smaller than any in the tree. 139 // Emulates splaying with a key that is smaller than any in the tree.
140 // After this, the smallest element in the tree is the root. 140 // After this, the smallest element in the tree is the root.
floitsch 2013/11/18 18:36:19 Update comment.
141 void _splayMin() { 141 _SplayTreeNode<K> _splayMin(_SplayTreeNode<K> node) {
142 assert(_root != null); 142 _SplayTreeNode current = node;
143 _SplayTreeNode current = _root;
144 while (current.left != null) { 143 while (current.left != null) {
145 _SplayTreeNode left = current.left; 144 _SplayTreeNode left = current.left;
146 current.left = left.right; 145 current.left = left.right;
147 left.right = current; 146 left.right = current;
148 current = left; 147 current = left;
149 } 148 }
150 _root = current; 149 return current;
151 } 150 }
152 151
153 // Emulates splaying with a key that is greater than any in the tree. 152 // Emulates splaying with a key that is greater than any in the tree.
154 // After this, the largest element in the tree is the root. 153 // After this, the largest element in the tree is the root.
floitsch 2013/11/18 18:36:19 Update the comment.
155 void _splayMax() { 154 _SplayTreeNode<K> _splayMax(_SplayTreeNode<K> node) {
156 assert(_root != null); 155 _SplayTreeNode current = node;
157 _SplayTreeNode current = _root;
158 while (current.right != null) { 156 while (current.right != null) {
159 _SplayTreeNode right = current.right; 157 _SplayTreeNode right = current.right;
160 current.right = right.left; 158 current.right = right.left;
161 right.left = current; 159 right.left = current;
162 current = right; 160 current = right;
163 } 161 }
164 _root = current; 162 return current;
165 } 163 }
166 164
167 _SplayTreeNode _remove(K key) { 165 _SplayTreeNode _remove(K key) {
168 if (_root == null) return null; 166 if (_root == null) return null;
169 int comp = _splay(key); 167 int comp = _splay(key);
170 if (comp != 0) return null; 168 if (comp != 0) return null;
171 _SplayTreeNode result = _root; 169 _SplayTreeNode result = _root;
172 _count--; 170 _count--;
173 // assert(_count >= 0); 171 // assert(_count >= 0);
174 if (_root.left == null) { 172 if (_root.left == null) {
175 _root = _root.right; 173 _root = _root.right;
176 } else { 174 } else {
177 _SplayTreeNode<K> right = _root.right; 175 _SplayTreeNode<K> right = _root.right;
178 _root = _root.left;
179 // Splay to make sure that the new root has an empty right child. 176 // Splay to make sure that the new root has an empty right child.
180 _splay(key); 177 _root = _splayMax(_root.left);
181 // Insert the original right child as the right child of the new 178 // Insert the original right child as the right child of the new
182 // root. 179 // root.
183 _root.right = right; 180 _root.right = right;
184 } 181 }
185 _modificationCount++; 182 _modificationCount++;
186 return result; 183 return result;
187 } 184 }
188 185
189 /** 186 /**
190 * Adds a new root node with the given [key] or [value]. 187 * Adds a new root node with the given [key] or [value].
(...skipping 16 matching lines...) Expand all
207 } else { 204 } else {
208 node.right = _root; 205 node.right = _root;
209 node.left = _root.left; 206 node.left = _root.left;
210 _root.left = null; 207 _root.left = null;
211 } 208 }
212 _root = node; 209 _root = node;
213 } 210 }
214 211
215 _SplayTreeNode get _first { 212 _SplayTreeNode get _first {
216 if (_root == null) return null; 213 if (_root == null) return null;
217 _splayMin(); 214 _root = _splayMin(_root);
218 return _root; 215 return _root;
219 } 216 }
220 217
221 _SplayTreeNode get _last { 218 _SplayTreeNode get _last {
222 if (_root == null) return null; 219 if (_root == null) return null;
223 _splayMax(); 220 _root = _splayMax(_root);
224 return _root; 221 return _root;
225 } 222 }
226 223
227 void _clear() { 224 void _clear() {
228 _root = null; 225 _root = null;
229 _count = 0; 226 _count = 0;
230 _modificationCount++; 227 _modificationCount++;
231 } 228 }
232 } 229 }
233 230
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after
488 * 485 *
489 * Only valid as long as the original tree isn't reordered. 486 * Only valid as long as the original tree isn't reordered.
490 */ 487 */
491 final List<_SplayTreeNode> _workList = <_SplayTreeNode>[]; 488 final List<_SplayTreeNode> _workList = <_SplayTreeNode>[];
492 489
493 /** 490 /**
494 * Original modification counter of [_tree]. 491 * Original modification counter of [_tree].
495 * 492 *
496 * Incremented on [_tree] when a key is added or removed. 493 * Incremented on [_tree] when a key is added or removed.
497 * If it changes, iteration is aborted. 494 * If it changes, iteration is aborted.
495 *
496 * Not final because some iterators may modify the tree knowingly,
497 * and they update the modification count in that case.
498 */ 498 */
499 final int _modificationCount; 499 int _modificationCount;
500 500
501 /** 501 /**
502 * Count of splay operations on [_tree] when [_workList] was built. 502 * Count of splay operations on [_tree] when [_workList] was built.
503 * 503 *
504 * If the splay count on [_tree] increases, [_workList] becomes invalid. 504 * If the splay count on [_tree] increases, [_workList] becomes invalid.
505 */ 505 */
506 int _splayCount; 506 int _splayCount;
507 507
508 /** Current node. */ 508 /** Current node. */
509 _SplayTreeNode _currentNode; 509 _SplayTreeNode _currentNode;
510 510
511 _SplayTreeIterator(_SplayTree tree) 511 _SplayTreeIterator(_SplayTree tree)
512 : _tree = tree, 512 : _tree = tree,
513 _modificationCount = tree._modificationCount, 513 _modificationCount = tree._modificationCount,
514 _splayCount = tree._splayCount { 514 _splayCount = tree._splayCount {
515 _findLeftMostDescendent(tree._root); 515 _findLeftMostDescendent(tree._root);
516 } 516 }
517 517
518 _SplayTreeIterator.startAt(_SplayTree tree, var startKey)
519 : _tree = tree,
520 _modificationCount = tree._modificationCount {
521 int compare = tree._splay(startKey);
522 _splayCount = tree._splayCount;
523 _findLeftMostDescendent(compare < 0 ? tree._root.right : tree._root);
524 }
525
518 T get current { 526 T get current {
519 if (_currentNode == null) return null; 527 if (_currentNode == null) return null;
520 return _getValue(_currentNode); 528 return _getValue(_currentNode);
521 } 529 }
522 530
531 _SplayTreeNode _findStartNode(K key) {
532
533 }
534
523 void _findLeftMostDescendent(_SplayTreeNode node) { 535 void _findLeftMostDescendent(_SplayTreeNode node) {
524 while (node != null) { 536 while (node != null) {
525 _workList.add(node); 537 _workList.add(node);
526 node = node.left; 538 node = node.left;
527 } 539 }
528 } 540 }
529 541
530 /** 542 /**
531 * Called when the tree structure of the tree has changed. 543 * Called when the tree structure of the tree has changed.
532 * 544 *
(...skipping 20 matching lines...) Expand all
553 } 565 }
554 // Picks the next element in the worklist as current. 566 // Picks the next element in the worklist as current.
555 // Updates the worklist with the left-most path of the current node's 567 // Updates the worklist with the left-most path of the current node's
556 // right-hand child. 568 // right-hand child.
557 // If the worklist is no longer valid (after a splay), it is rebuild 569 // If the worklist is no longer valid (after a splay), it is rebuild
558 // from scratch. 570 // from scratch.
559 if (_workList.isEmpty) { 571 if (_workList.isEmpty) {
560 _currentNode = null; 572 _currentNode = null;
561 return false; 573 return false;
562 } 574 }
563 if (_tree._splayCount != _splayCount) { 575 if (_tree._splayCount != _splayCount && _currentNode != null) {
564 _rebuildWorkList(_currentNode); 576 _rebuildWorkList(_currentNode);
565 } 577 }
566 _currentNode = _workList.removeLast(); 578 _currentNode = _workList.removeLast();
567 _findLeftMostDescendent(_currentNode.right); 579 _findLeftMostDescendent(_currentNode.right);
568 return true; 580 return true;
569 } 581 }
570 582
571 T _getValue(_SplayTreeNode node); 583 T _getValue(_SplayTreeNode node);
572 } 584 }
573 585
(...skipping 20 matching lines...) Expand all
594 K _getValue(_SplayTreeNode node) => node.key; 606 K _getValue(_SplayTreeNode node) => node.key;
595 } 607 }
596 608
597 class _SplayTreeValueIterator<K, V> extends _SplayTreeIterator<V> { 609 class _SplayTreeValueIterator<K, V> extends _SplayTreeIterator<V> {
598 _SplayTreeValueIterator(SplayTreeMap<K, V> map): super(map); 610 _SplayTreeValueIterator(SplayTreeMap<K, V> map): super(map);
599 V _getValue(_SplayTreeMapNode node) => node.value; 611 V _getValue(_SplayTreeMapNode node) => node.value;
600 } 612 }
601 613
602 class _SplayTreeNodeIterator<K> 614 class _SplayTreeNodeIterator<K>
603 extends _SplayTreeIterator<_SplayTreeNode<K>> { 615 extends _SplayTreeIterator<_SplayTreeNode<K>> {
604 _SplayTreeNodeIterator(_SplayTree<K> map): super(map); 616 _SplayTreeNodeIterator(_SplayTree<K> tree): super(tree);
617 _SplayTreeNodeIterator.startAt(_SplayTree<K> tree, var startKey)
618 : super.startAt(tree, startKey);
605 _SplayTreeNode<K> _getValue(_SplayTreeNode node) => node; 619 _SplayTreeNode<K> _getValue(_SplayTreeNode node) => node;
606 } 620 }
621
622
623 class SplayTreeSet<E> extends _SplayTree<E> with IterableMixin<E>
624 implements Set<E> {
625 Comparator _comparator;
626 _Predicate _validKey;
627 SplayTreeSet([int compare(E key1, E key2), bool isValidKey(potentialKey)])
628 : _comparator = (compare == null) ? Comparable.compare : compare,
629 _validKey = (isValidKey != null) ? isValidKey : ((v) => v is E);
630
631 int _compare(E e1, E e2) => _comparator(e1, e2);
632
633 // From Iterable.
634
635 Iterator<E> get iterator => new _SplayTreeKeyIterator<E>(this);
636
637 int get length => _count;
638 bool get isEmpty => _root == null;
639 bool get isNotEmpty => _root != null;
640
641 E get first {
642 if (_count == 0) throw new StateError("no such element");
643 return _first.key;
644 }
645
646 E get last {
647 if (_count == 0) throw new StateError("no such element");
648 return _last.key;
649 }
650
651 E get single {
652 if (_count == 0) throw new StateError("no such element");
653 if (_count > 1) throw new StateError("too many elements");
654 return _root.key;
655 }
656
657 // From Set.
658 bool contains(Object object) {
659 return _validKey(object) && _splay(object) == 0;
660 }
661
662 bool add(E element) {
663 int compare = _splay(element);
664 if (compare == 0) return false;
665 _addNewRoot(new _SplayTreeNode(element), compare);
666 return true;
667 }
668
669 bool remove(Object object) {
670 if (!_validKey(object)) return false;
671 return _remove(object) != null;
672 }
673
674 void addAll(Iterable<E> elements) {
675 for (E element in elements) {
676 int compare = _splay(element);
677 if (compare != 0) {
678 _addNewRoot(new _SplayTreeNode(element), compare);
679 }
680 }
681 }
682
683 void removeAll(Iterable elements) {
684 for (Object element in elements) {
685 if (_validKey(element)) _remove(element);
686 }
687 }
688
689 /**
690 * Removes all elements not in [elements].
691 */
692 void retainAll(Iterable<Object> elements) {
693 // Build a set with the same sense of equality as this set.
694 Set<E> retainSet = new SplayTreeSet<E>(_comparator, _validKey);
695 int modificationCount = _modificationCount;
696 for (Object object in elements) {
697 if (modificationCount != _modificationCount) {
698 // The iterator should not have side effects.
699 throw new ConcurrentModificationError(this);
700 }
701 if (this.contains(object)) retainSet.add(object);
702 }
703 // Take over the elements from the retained set, if it differs.
704 if (retainSet._count != _count) {
705 _root = retainSet._root;
706 _count = retainSet._count;
707 _modificationCount++;
708 }
709 }
710
711 void _filterWhere(bool test(E element), bool removeMatching) {
712 _SplayTreeNodeIterator it = new _SplayTreeNodeIterator(this);
713 while (it.moveNext()) {
714 _SplayTreeNode node = it.current;
715 int modificationCount = _modificationCount;
716 bool matches = test(node.key);
717 if (modificationCount != _modificationCount) {
718 throw new ConcurrentModificationError(this);
719 }
720 if (matches == removeMatching) {
721 _remove(node.key);
722 it = new _SplayTreeNodeIterator.startAt(this, node.key);
723 }
724 }
725 }
726
727 void removeWhere(bool test(E element)) {
728 _filterWhere(test, true);
729 }
730
731 void retainWhere(bool test(E element)) {
732 _filterWhere(test, false);
733 }
734
735 E lookup(Object object) {
736 if (!_validKey(object)) return null;
737 int comp = _splay(object);
738 if (comp != 0) return null;
739 return _root.key;
740 }
741
742 Set<E> intersection(Set<E> other) {
743 Set<E> result = new SplayTreeSet<E>();
744 for (E element in this) {
745 if (other.contains(element)) result.add(element);
746 }
747 return result;
748 }
749
750 Set<E> difference(Set<E> other) {
751 Set<E> result = new SplayTreeSet<E>();
752 for (E element in this) {
753 if (!other.contains(element)) result.add(element);
754 }
755 return result;
756 }
757
758 Set<E> union(Set<E> other) {
759 return _clone()..addAll(other);
760 }
761
762 SplayTreeSet<E> _clone() {
763 var set = new SplayTreeSet<E>();
764 set._count = _count;
765 set._root = _cloneNode(_root);
766 return set;
767 }
768
769 _SplayTreeNode<E> _cloneNode(_SplayTreeNode<E> node) {
770 if (node == null) return null;
771 return new _SplayTreeNode<E>(node.key)..left = _cloneNode(node.left)
772 ..right = _cloneNode(node.right);
773 }
774
775 bool containsAll(Iterable other) {
776 for (var element in other) {
777 if (!this.contains(element)) return false;
778 }
779 return true;
780 }
781
782 void clear() { _clear(); }
783 }
OLDNEW
« no previous file with comments | « sdk/lib/collection/hash_set.dart ('k') | sdk/lib/core/set.dart » ('j') | sdk/lib/core/set.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698