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

Side by Side Diff: quiver/lib/src/collection/treeset.dart

Issue 1400473008: Roll Observatory packages and add a roll script (Closed) Base URL: git@github.com:dart-lang/observatory_pub_packages.git@master
Patch Set: Created 5 years, 2 months 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
« no previous file with comments | « quiver/lib/src/collection/multimap.dart ('k') | quiver/lib/src/core/hash.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2014 Google Inc. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 part of quiver.collection;
16
17 /**
18 * A [Set] of items stored in a binary tree according to [comparator].
19 * Supports bidirectional iteration.
20 */
21 abstract class TreeSet<V> extends IterableBase<V> implements Set<V> {
22 final Comparator<V> comparator;
23
24 int get length;
25
26 /**
27 * Create a new [TreeSet] with an ordering defined by [comparator] or the
28 * default `(a, b) => a.compareTo(b)`.
29 */
30 factory TreeSet({Comparator<V> comparator}) {
31 if (comparator == null) {
32 comparator = (a, b) => a.compareTo(b);
33 }
34 return new AvlTreeSet(comparator: comparator);
35 }
36
37 TreeSet._(this.comparator);
38
39 /**
40 * Returns an [BidirectionalIterator] that iterates over this tree.
41 */
42 BidirectionalIterator<V> get iterator;
43
44 /**
45 * Returns an [BidirectionalIterator] that iterates over this tree, in reverse .
46 */
47 BidirectionalIterator<V> get reverseIterator;
48
49 /**
50 * Returns an [BidirectionalIterator] that starts at [anchor].
51 * By default, the iterator includes the anchor with the first movement;
52 * set [inclusive] to false if you want to exclude the anchor. Set [reversed]
53 * to true to change the direction of of moveNext and movePrevious.
54 *
55 * Note: This iterator allows you to walk the entire set. It does not present
56 * a subview.
57 */
58 BidirectionalIterator<V> fromIterator(V anchor,
59 {bool reversed: false, bool inclusive: true});
60
61 /**
62 * Search the tree for the matching [object] or the [nearestOption]
63 * if missing. See [TreeSearch].
64 */
65 V nearest(V object, {TreeSearch nearestOption: TreeSearch.NEAREST});
66
67 // TODO: toString or not toString, that is the question.
68 }
69
70 /**
71 * Controls the results for [TreeSet.searchNearest]()
72 */
73 class TreeSearch {
74
75 /**
76 * If result not found, always chose the smaler element
77 */
78 static const LESS_THAN = const TreeSearch._(1);
79
80 /**
81 * If result not found, chose the nearest based on comparison
82 */
83 static const NEAREST = const TreeSearch._(2);
84
85 /**
86 * If result not found, always chose the greater element
87 */
88 static const GREATER_THAN = const TreeSearch._(3);
89
90 final int _val;
91 const TreeSearch._(this._val);
92 }
93
94 /**
95 * A node in the [TreeSet].
96 */
97 abstract class _TreeNode<V> {
98 _TreeNode<V> get left;
99 _TreeNode<V> get right;
100
101 //TODO(codefu): Remove need for [parent]; this is just an implementation note
102 _TreeNode<V> get parent;
103 V object;
104
105 /**
106 * TreeNodes are always allocated as leafs.
107 */
108 _TreeNode({this.object});
109
110 /**
111 * Return the minimum node for the subtree
112 */
113 _TreeNode<V> get minimumNode {
114 var node = this;
115 while (node.left != null) {
116 node = node.left;
117 }
118 return node;
119 }
120
121 /**
122 * Return the maximum node for the subtree
123 */
124 _TreeNode<V> get maximumNode {
125 var node = this;
126 while (node.right != null) {
127 node = node.right;
128 }
129 return node;
130 }
131
132 /**
133 * Return the next greatest element (or null)
134 */
135 _TreeNode<V> get successor {
136 var node = this;
137 if (node.right != null) {
138 return node.right.minimumNode;
139 }
140 while (node.parent != null && node == node.parent.right) {
141 node = node.parent;
142 }
143 return node.parent;
144 }
145
146 /**
147 * Return the next smaller element (or null)
148 */
149 _TreeNode<V> get predecessor {
150 var node = this;
151 if (node.left != null) {
152 return node.left.maximumNode;
153 }
154 while (node.parent != null && node.parent._left == node) {
155 node = node.parent;
156 }
157 return node.parent;
158 }
159 }
160
161 /**
162 * AVL implementation of a self-balancing binary tree. Optimized for lookup
163 * operations.
164 *
165 * Notes: Adapted from "Introduction to Algorithms", second edition,
166 * by Thomas H. Cormen, Charles E. Leiserson,
167 * Ronald L. Rivest, Clifford Stein.
168 * chapter 13.2
169 */
170 class AvlTreeSet<V> extends TreeSet<V> {
171 int _length = 0;
172 AvlNode<V> _root;
173 // Modification count to the tree, monotonically increasing
174 int _modCount = 0;
175
176 int get length => _length;
177
178 AvlTreeSet({Comparator<V> comparator}) : super._(comparator);
179
180 /**
181 * Add the element to the tree.
182 */
183 bool add(V element) {
184 if (_root == null) {
185 AvlNode<V> node = new AvlNode<V>(object: element);
186 _root = node;
187 ++_length;
188 ++_modCount;
189 return true;
190 }
191
192 AvlNode<V> x = _root;
193 while (true) {
194 int compare = comparator(element, x.object);
195 if (compare == 0) {
196 return false;
197 } else if (compare < 0) {
198 if (x._left == null) {
199 AvlNode<V> node = new AvlNode<V>(object: element).._parent = x;
200 x
201 .._left = node
202 .._balanceFactor -= 1;
203 break;
204 }
205 x = x.left;
206 } else {
207 if (x._right == null) {
208 AvlNode<V> node = new AvlNode<V>(object: element).._parent = x;
209 x
210 .._right = node
211 .._balanceFactor += 1;
212 break;
213 }
214 x = x.right;
215 }
216 }
217
218 ++_modCount;
219
220 // AVL balancing act (for height balanced trees)
221 // Now that we've inserted, we've unbalanced some trees, we need
222 // to follow the tree back up to the _root double checking that the tree
223 // is still balanced and _maybe_ perform a single or double rotation.
224 // Note: Left additions == -1, Right additions == +1
225 // Balanced Node = { -1, 0, 1 }, out of balance = { -2, 2 }
226 // Single rotation when Parent & Child share signed balance,
227 // Double rotation when sign differs!
228 AvlNode<V> node = x;
229 while (node._balanceFactor != 0 && node.parent != null) {
230 // Find out which side of the parent we're on
231 if (node.parent._left == node) {
232 node.parent._balanceFactor -= 1;
233 } else {
234 node.parent._balanceFactor += 1;
235 }
236
237 node = node.parent;
238 if (node._balanceFactor == 2) {
239 // Heavy on the right side - Test for which rotation to perform
240 if (node.right._balanceFactor == 1) {
241 // Single (left) rotation; this will balance everything to zero
242 _rotateLeft(node);
243 node._balanceFactor = node.parent._balanceFactor = 0;
244 node = node.parent;
245 } else {
246 // Double (Right/Left) rotation
247 // node will now be old node.right.left
248 _rotateRightLeft(node);
249 node = node.parent; // Update to new parent (old grandchild)
250 if (node._balanceFactor == 1) {
251 node.right._balanceFactor = 0;
252 node.left._balanceFactor = -1;
253 } else if (node._balanceFactor == 0) {
254 node.right._balanceFactor = 0;
255 node.left._balanceFactor = 0;
256 } else {
257 node.right._balanceFactor = 1;
258 node.left._balanceFactor = 0;
259 }
260 node._balanceFactor = 0;
261 }
262 break; // out of loop, we're balanced
263 } else if (node._balanceFactor == -2) {
264 // Heavy on the left side - Test for which rotation to perform
265 if (node.left._balanceFactor == -1) {
266 _rotateRight(node);
267 node._balanceFactor = node.parent._balanceFactor = 0;
268 node = node.parent;
269 } else {
270 // Double (Left/Right) rotation
271 // node will now be old node.left.right
272 _rotateLeftRight(node);
273 node = node.parent;
274 if (node._balanceFactor == -1) {
275 node.right._balanceFactor = 1;
276 node.left._balanceFactor = 0;
277 } else if (node._balanceFactor == 0) {
278 node.right._balanceFactor = 0;
279 node.left._balanceFactor = 0;
280 } else {
281 node.right._balanceFactor = 0;
282 node.left._balanceFactor = -1;
283 }
284 node._balanceFactor = 0;
285 }
286 break; // out of loop, we're balanced
287 }
288 } // end of while (balancing)
289 _length++;
290 return true;
291 }
292
293 /**
294 * Test to see if an element is stored in the tree
295 */
296 AvlNode<V> _getNode(V element) {
297 if (element == null) return null;
298 AvlNode<V> x = _root;
299 while (x != null) {
300 int compare = comparator(element, x.object);
301 if (compare == 0) {
302 // This only means our node matches; we need to search for the exact
303 // element. We could have been glutons and used a hashmap to back.
304 return x;
305 } else if (compare < 0) {
306 x = x.left;
307 } else {
308 x = x.right;
309 }
310 }
311 return null;
312 }
313
314 /**
315 * This function will right rotate/pivot N with its left child, placing
316 * it on the right of its left child.
317 *
318 * N Y
319 * / \ / \
320 * Y A Z N
321 * / \ ==> / \ / \
322 * Z B D CB A
323 * / \
324 *D C
325 *
326 * Assertion: must have a left element
327 */
328 void _rotateRight(AvlNode<V> node) {
329 AvlNode<V> y = node.left;
330 if (y == null) throw new AssertionError();
331
332 // turn Y's right subtree(B) into N's left subtree.
333 node._left = y.right;
334 if (node.left != null) {
335 node.left._parent = node;
336 }
337 y._parent = node.parent;
338 if (y._parent == null) {
339 _root = y;
340 } else {
341 if (node.parent._left == node) {
342 node.parent._left = y;
343 } else {
344 node.parent._right = y;
345 }
346 }
347 y._right = node;
348 node._parent = y;
349 }
350
351 /**
352 * This function will left rotate/pivot N with its right child, placing
353 * it on the left of its right child.
354 *
355 * N Y
356 * / \ / \
357 * A Y N Z
358 * / \ ==> / \ / \
359 * B Z A BC D
360 * / \
361 * C D
362 *
363 * Assertion: must have a right element
364 */
365 void _rotateLeft(AvlNode<V> node) {
366 AvlNode<V> y = node.right;
367 if (y == null) throw new AssertionError();
368
369 // turn Y's left subtree(B) into N's right subtree.
370 node._right = y.left;
371 if (node.right != null) {
372 node.right._parent = node;
373 }
374 y._parent = node.parent;
375 if (y._parent == null) {
376 _root = y;
377 } else {
378 if (node.parent._left == node) {
379 y.parent._left = y;
380 } else {
381 y.parent._right = y;
382 }
383 }
384 y._left = node;
385 node._parent = y;
386 }
387
388 /**
389 * This function will double rotate node with right/left operations.
390 * node is S.
391 *
392 * S G
393 * / \ / \
394 * A C S C
395 * / \ ==> / \ / \
396 * G B A DC B
397 * / \
398 * D C
399 */
400 void _rotateRightLeft(AvlNode<V> node) {
401 _rotateRight(node.right);
402 _rotateLeft(node);
403 }
404
405 /**
406 * This function will double rotate node with left/right operations.
407 * node is S.
408 *
409 * S G
410 * / \ / \
411 * C A C S
412 * / \ ==> / \ / \
413 *B G B CD A
414 * / \
415 * C D
416 */
417 void _rotateLeftRight(AvlNode<V> node) {
418 _rotateLeft(node.left);
419 _rotateRight(node);
420 }
421
422 bool addAll(Iterable<V> items) {
423 bool modified = false;
424 for (V ele in items) {
425 modified = add(ele) ? true : modified;
426 }
427 return modified;
428 }
429
430 void clear() {
431 _length = 0;
432 _root = null;
433 ++_modCount;
434 }
435
436 bool containsAll(Iterable<Object> items) {
437 for (var ele in items) {
438 if (!contains(ele)) return false;
439 }
440 return true;
441 }
442
443 bool remove(Object item) {
444 AvlNode<V> x = _getNode(item);
445 if (x != null) {
446 _removeNode(x);
447 return true;
448 }
449 return false;
450 }
451
452 void _removeNode(AvlNode<V> node) {
453 AvlNode<V> y, w;
454
455 ++_modCount;
456 --_length;
457
458 // note: if you read wikipedia, it states remove the node if its a leaf,
459 // otherwise, replace it with its predecessor or successor. We're not.
460 if (node._right == null || node.right._left == null) {
461 // simple solutions
462 if (node.right != null) {
463 y = node.right;
464 y._parent = node.parent;
465 y._balanceFactor = node._balanceFactor - 1;
466 y._left = node.left;
467 if (y.left != null) {
468 y.left._parent = y;
469 }
470 } else if (node.left != null) {
471 y = node.left;
472 y._parent = node.parent;
473 y._balanceFactor = node._balanceFactor + 1;
474 } else {
475 y = null;
476 }
477 if (_root == node) {
478 _root = y;
479 } else if (node.parent._left == node) {
480 node.parent._left = y;
481 if (y == null) {
482 // account for leaf deletions changing the balance
483 node.parent._balanceFactor += 1;
484 y = node.parent; // start searching from here;
485 }
486 } else {
487 node.parent._right = y;
488 if (y == null) {
489 node.parent._balanceFactor -= 1;
490 y = node.parent;
491 }
492 }
493 w = y;
494 } else {
495 // This node is not a leaf; we should find the successor node, swap
496 //it with this* and then update the balance factors.
497 y = node.successor;
498 y._left = node.left;
499 if (y.left != null) {
500 y.left._parent = y;
501 }
502
503 w = y.parent;
504 w._left = y.right;
505 if (w.left != null) {
506 w.left._parent = w;
507 }
508 // known: we're removing from the left
509 w._balanceFactor += 1;
510
511 // known due to test for n->r->l above
512 y._right = node.right;
513 y.right._parent = y;
514 y._balanceFactor = node._balanceFactor;
515
516 y._parent = node.parent;
517 if (_root == node) {
518 _root = y;
519 } else if (node.parent._left == node) {
520 node.parent._left = y;
521 } else {
522 node.parent._right = y;
523 }
524 }
525
526 // Safe to kill node now; its free to go.
527 node._balanceFactor = 0;
528 node._left = node._right = node._parent = null;
529 node.object = null;
530
531 // Recalculate max values all the way to the top.
532 node = w;
533 while (node != null) {
534 node = node.parent;
535 }
536
537 // Re-balance to the top, ending early if OK
538 node = w;
539 while (node != null) {
540 if (node._balanceFactor == -1 || node._balanceFactor == 1) {
541 // The height of node hasn't changed; done!
542 break;
543 }
544 if (node._balanceFactor == 2) {
545 // Heavy on the right side; figure out which rotation to perform
546 if (node.right._balanceFactor == -1) {
547 _rotateRightLeft(node);
548 node = node.parent; // old grand-child!
549 if (node._balanceFactor == 1) {
550 node.right._balanceFactor = 0;
551 node.left._balanceFactor = -1;
552 } else if (node._balanceFactor == 0) {
553 node.right._balanceFactor = 0;
554 node.left._balanceFactor = 0;
555 } else {
556 node.right._balanceFactor = 1;
557 node.left._balanceFactor = 0;
558 }
559 node._balanceFactor = 0;
560 } else {
561 // single left-rotation
562 _rotateLeft(node);
563 if (node.parent._balanceFactor == 0) {
564 node.parent._balanceFactor = -1;
565 node._balanceFactor = 1;
566 break;
567 } else {
568 node.parent._balanceFactor = 0;
569 node._balanceFactor = 0;
570 node = node.parent;
571 continue;
572 }
573 }
574 } else if (node._balanceFactor == -2) {
575 // Heavy on the left
576 if (node.left._balanceFactor == 1) {
577 _rotateLeftRight(node);
578 node = node.parent; // old grand-child!
579 if (node._balanceFactor == -1) {
580 node.right._balanceFactor = 1;
581 node.left._balanceFactor = 0;
582 } else if (node._balanceFactor == 0) {
583 node.right._balanceFactor = 0;
584 node.left._balanceFactor = 0;
585 } else {
586 node.right._balanceFactor = 0;
587 node.left._balanceFactor = -1;
588 }
589 node._balanceFactor = 0;
590 } else {
591 _rotateRight(node);
592 if (node.parent._balanceFactor == 0) {
593 node.parent._balanceFactor = 1;
594 node._balanceFactor = -1;
595 break;
596 } else {
597 node.parent._balanceFactor = 0;
598 node._balanceFactor = 0;
599 node = node.parent;
600 continue;
601 }
602 }
603 }
604
605 // continue up the tree for testing
606 if (node.parent != null) {
607 // The concept of balance here is reverse from addition; since
608 // we are taking away weight from one side or the other (thus
609 // the balance changes in favor of the other side)
610 if (node.parent.left == node) {
611 node.parent._balanceFactor += 1;
612 } else {
613 node.parent._balanceFactor -= 1;
614 }
615 }
616 node = node.parent;
617 }
618 }
619
620 /**
621 * See [Set.removeAll]
622 */
623 void removeAll(Iterable items) {
624 for (var ele in items) {
625 remove(ele);
626 }
627 }
628
629 /**
630 * See [Set.retainAll]
631 */
632 void retainAll(Iterable<Object> elements) {
633 List<V> chosen = [];
634 for (var target in elements) {
635 if (contains(target)) {
636 chosen.add(target);
637 }
638 }
639 clear();
640 addAll(chosen);
641 }
642
643 /**
644 * See [Set.retainWhere]
645 */
646 void retainWhere(bool test(V element)) {
647 List<V> chosen = [];
648 for (var target in this) {
649 if (test(target)) {
650 chosen.add(target);
651 }
652 }
653 clear();
654 addAll(chosen);
655 }
656
657 /**
658 * See [Set.removeWhere]
659 */
660 void removeWhere(bool test(V element)) {
661 List<V> damned = [];
662 for (var target in this) {
663 if (test(target)) {
664 damned.add(target);
665 }
666 }
667 removeAll(damned);
668 }
669
670 /**
671 * See [IterableBase.first]
672 */
673 V get first {
674 if (_root == null) return null;
675 AvlNode<V> min = _root.minimumNode;
676 return min != null ? min.object : null;
677 }
678
679 /**
680 * See [IterableBase.last]
681 */
682 V get last {
683 if (_root == null) return null;
684 AvlNode<V> max = _root.maximumNode;
685 return max != null ? max.object : null;
686 }
687
688 /**
689 * See [Set.lookup]
690 */
691 V lookup(Object element) {
692 if (element == null || _root == null) return null;
693 AvlNode<V> x = _root;
694 int compare = 0;
695 while (x != null) {
696 compare = comparator(element, x.object);
697 if (compare == 0) {
698 return x.object;
699 } else if (compare < 0) {
700 x = x.left;
701 } else {
702 x = x.right;
703 }
704 }
705 return null;
706 }
707
708 V nearest(V object, {TreeSearch nearestOption: TreeSearch.NEAREST}) {
709 AvlNode<V> found = _searchNearest(object, option: nearestOption);
710 return (found != null) ? found.object : null;
711 }
712
713 /**
714 * Search the tree for the matching element, or the 'nearest' node.
715 * NOTE: [BinaryTree.comparator] needs to have finer granulatity than -1,0,1
716 * in order for this to return something that's meaningful.
717 */
718 AvlNode<V> _searchNearest(V element,
719 {TreeSearch option: TreeSearch.NEAREST}) {
720 if (element == null || _root == null) {
721 return null;
722 }
723 AvlNode<V> x = _root;
724 AvlNode<V> previous;
725 int compare = 0;
726 while (x != null) {
727 previous = x;
728 compare = comparator(element, x.object);
729 if (compare == 0) {
730 return x;
731 } else if (compare < 0) {
732 x = x.left;
733 } else {
734 x = x.right;
735 }
736 }
737
738 if (option == TreeSearch.GREATER_THAN) {
739 return (compare < 0) ? previous : previous.successor;
740 } else if (option == TreeSearch.LESS_THAN) {
741 return (compare < 0) ? previous.predecessor : previous;
742 }
743 // Default: nearest absolute value
744 // Fell off the tree looking for the exact match; now we need
745 // to find the nearest element.
746 x = (compare < 0) ? previous.predecessor : previous.successor;
747 if (x == null) {
748 return previous;
749 }
750 int otherCompare = comparator(element, x.object);
751 if (compare < 0) {
752 return compare.abs() < otherCompare ? previous : x;
753 }
754 return otherCompare.abs() < compare ? x : previous;
755 }
756
757 //
758 // [IterableBase]<V> Methods
759 //
760
761 /**
762 * See [IterableBase.iterator]
763 */
764 BidirectionalIterator<V> get iterator => new _AvlTreeIterator._(this);
765
766 /**
767 * See [TreeSet.reverseIterator]
768 */
769 BidirectionalIterator<V> get reverseIterator =>
770 new _AvlTreeIterator._(this, reversed: true);
771
772 /**
773 * See [TreeSet.fromIterator]
774 */
775 BidirectionalIterator<V> fromIterator(V anchor,
776 {bool reversed: false, bool inclusive: true}) =>
777 new _AvlTreeIterator<V>._(this,
778 anchorObject: anchor, reversed: reversed, inclusive: inclusive);
779
780 /**
781 * See [IterableBase.contains]
782 */
783 bool contains(Object object) {
784 AvlNode<V> x = _getNode(object as V);
785 return x != null;
786 }
787
788 //
789 // [Set] methods
790 //
791
792 /**
793 * See [Set.intersection]
794 */
795 Set<V> intersection(Set<Object> other) {
796 TreeSet<V> set = new TreeSet(comparator: comparator);
797
798 // Opitimized for sorted sets
799 if (other is TreeSet) {
800 var i1 = iterator;
801 var i2 = other.iterator;
802 var hasMore1 = i1.moveNext();
803 var hasMore2 = i2.moveNext();
804 while (hasMore1 && hasMore2) {
805 var c = comparator(i1.current, i2.current);
806 if (c == 0) {
807 set.add(i1.current);
808 hasMore1 = i1.moveNext();
809 hasMore2 = i2.moveNext();
810 } else if (c < 0) {
811 hasMore1 = i1.moveNext();
812 } else {
813 hasMore2 = i2.moveNext();
814 }
815 }
816 return set;
817 }
818
819 // Non-optimized version.
820 for (var target in this) {
821 if (other.contains(target)) {
822 set.add(target);
823 }
824 }
825 return set;
826 }
827
828 /**
829 * See [Set.union]
830 */
831 Set<V> union(Set<V> other) {
832 TreeSet<V> set = new TreeSet(comparator: comparator);
833
834 if (other is TreeSet) {
835 var i1 = iterator;
836 var i2 = other.iterator;
837 var hasMore1 = i1.moveNext();
838 var hasMore2 = i2.moveNext();
839 while (hasMore1 && hasMore2) {
840 var c = comparator(i1.current, i2.current);
841 if (c == 0) {
842 set.add(i1.current);
843 hasMore1 = i1.moveNext();
844 hasMore2 = i2.moveNext();
845 } else if (c < 0) {
846 set.add(i1.current);
847 hasMore1 = i1.moveNext();
848 } else {
849 set.add(i2.current);
850 hasMore2 = i2.moveNext();
851 }
852 }
853 if (hasMore1 || hasMore2) {
854 i1 = hasMore1 ? i1 : i2;
855 do {
856 set.add(i1.current);
857 } while (i1.moveNext());
858 }
859 return set;
860 }
861
862 // Non-optimized version.
863 return set
864 ..addAll(this)
865 ..addAll(other);
866 }
867
868 /**
869 * See [Set.difference]
870 */
871 Set<V> difference(Set<V> other) {
872 TreeSet<V> set = new TreeSet(comparator: comparator);
873
874 if (other is TreeSet) {
875 var i1 = iterator;
876 var i2 = other.iterator;
877 var hasMore1 = i1.moveNext();
878 var hasMore2 = i2.moveNext();
879 while (hasMore1 && hasMore2) {
880 var c = comparator(i1.current, i2.current);
881 if (c == 0) {
882 hasMore1 = i1.moveNext();
883 hasMore2 = i2.moveNext();
884 } else if (c < 0) {
885 set.add(i1.current);
886 hasMore1 = i1.moveNext();
887 } else {
888 hasMore2 = i2.moveNext();
889 }
890 }
891 if (hasMore1) {
892 do {
893 set.add(i1.current);
894 } while (i1.moveNext());
895 }
896 return set;
897 }
898
899 // Non-optimized version.
900 for (var target in this) {
901 if (!other.contains(target)) {
902 set.add(target);
903 }
904 }
905 return set;
906 }
907
908 /**
909 * Visible for testing only.
910 */
911 AvlNode<V> getNode(V object) => _getNode(object);
912 }
913
914 typedef bool _IteratorMove();
915
916 /**
917 * This iterator either starts at the beginning or end (see [TreeSet.iterator]
918 * and [TreeSet.reverseIterator]) or from an anchor point in the set (see
919 * [TreeSet.fromIterator]). When using fromIterator, the inital
920 * anchor point is included in the first movement (either [moveNext] or
921 * [movePrevious]) but can optionally be excluded in the constructor.
922 */
923 class _AvlTreeIterator<V> implements BidirectionalIterator<V> {
924 static const LEFT = -1;
925 static const WALK = 0;
926 static const RIGHT = 1;
927
928 final bool reversed;
929 final AvlTreeSet<V> tree;
930 final int _modCountGuard;
931 final Object anchorObject;
932 final bool inclusive;
933
934 _IteratorMove _moveNext;
935 _IteratorMove _movePrevious;
936
937 int state;
938 _TreeNode<V> _current;
939
940 _AvlTreeIterator._(AvlTreeSet<V> tree,
941 {reversed: false, this.inclusive: true, this.anchorObject: null})
942 : this.tree = tree,
943 this._modCountGuard = tree._modCount,
944 this.reversed = reversed {
945 if (anchorObject == null || tree.length == 0) {
946 // If the anchor is far left or right, we're just a normal iterator.
947 state = reversed ? RIGHT : LEFT;
948 _moveNext = reversed ? _movePreviousNormal : _moveNextNormal;
949 _movePrevious = reversed ? _moveNextNormal : _movePreviousNormal;
950 return;
951 }
952
953 state = WALK;
954 // Else we've got an anchor we have to worry about initalizing from.
955 // This isn't known till the caller actually performs a previous/next.
956 _moveNext = () {
957 _current = tree._searchNearest(anchorObject,
958 option: reversed ? TreeSearch.LESS_THAN : TreeSearch.GREATER_THAN);
959 _moveNext = reversed ? _movePreviousNormal : _moveNextNormal;
960 _movePrevious = reversed ? _moveNextNormal : _movePreviousNormal;
961 if (_current == null) {
962 state = reversed ? LEFT : RIGHT;
963 } else if (tree.comparator(_current.object, anchorObject) == 0 &&
964 !inclusive) {
965 _moveNext();
966 }
967 return state == WALK;
968 };
969
970 _movePrevious = () {
971 _current = tree._searchNearest(anchorObject,
972 option: reversed ? TreeSearch.GREATER_THAN : TreeSearch.LESS_THAN);
973 _moveNext = reversed ? _movePreviousNormal : _moveNextNormal;
974 _movePrevious = reversed ? _moveNextNormal : _movePreviousNormal;
975 if (_current == null) {
976 state = reversed ? RIGHT : LEFT;
977 } else if (tree.comparator(_current.object, anchorObject) == 0 &&
978 !inclusive) {
979 _movePrevious();
980 }
981 return state == WALK;
982 };
983 }
984
985 V get current => (state != WALK || _current == null) ? null : _current.object;
986
987 bool moveNext() => _moveNext();
988 bool movePrevious() => _movePrevious();
989
990 bool _moveNextNormal() {
991 if (_modCountGuard != tree._modCount) {
992 throw new ConcurrentModificationError(tree);
993 }
994 if (state == RIGHT || tree.length == 0) return false;
995 switch (state) {
996 case LEFT:
997 _current = tree._root.minimumNode;
998 state = WALK;
999 return true;
1000 case WALK:
1001 default:
1002 _current = _current.successor;
1003 if (_current == null) {
1004 state = RIGHT;
1005 }
1006 return state == WALK;
1007 }
1008 }
1009
1010 bool _movePreviousNormal() {
1011 if (_modCountGuard != tree._modCount) {
1012 throw new ConcurrentModificationError(tree);
1013 }
1014 if (state == LEFT || tree.length == 0) return false;
1015 switch (state) {
1016 case RIGHT:
1017 _current = tree._root.maximumNode;
1018 state = WALK;
1019 return true;
1020 case WALK:
1021 default:
1022 _current = _current.predecessor;
1023 if (_current == null) {
1024 state = LEFT;
1025 }
1026 return state == WALK;
1027 }
1028 }
1029 }
1030
1031 /**
1032 * Private class used to track element insertions in the [TreeSet].
1033 */
1034 class AvlNode<V> extends _TreeNode<V> {
1035 AvlNode<V> _left;
1036 AvlNode<V> _right;
1037 //TODO(codefu): Remove need for [parent]; this is just an implementation note
1038 AvlNode<V> _parent;
1039 int _balanceFactor = 0;
1040
1041 AvlNode<V> get left => _left;
1042 AvlNode<V> get right => _right;
1043 AvlNode<V> get parent => _parent;
1044 int get balance => _balanceFactor;
1045
1046 AvlNode({V object}) : super(object: object);
1047
1048 String toString() =>
1049 "(b:$balance o: $object l:${left != null} r:${right != null})";
1050 }
OLDNEW
« no previous file with comments | « quiver/lib/src/collection/multimap.dart ('k') | quiver/lib/src/core/hash.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698