OLD | NEW |
| (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 } | |
OLD | NEW |