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

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

Powered by Google App Engine
This is Rietveld 408576698