OLD | NEW |
1 // Copyright 2014 Google Inc. All Rights Reserved. | 1 // Copyright 2014 Google Inc. All Rights Reserved. |
2 // | 2 // |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
4 // you may not use this file except in compliance with 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 | 5 // You may obtain a copy of the License at |
6 // | 6 // |
7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
8 // | 8 // |
9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 // See the License for the specific language governing permissions and | 12 // See the License for the specific language governing permissions and |
13 // limitations under the License. | 13 // limitations under the License. |
14 | 14 |
15 part of quiver.collection; | 15 part of quiver.collection; |
16 | 16 |
17 /** | 17 /// A [Set] of items stored in a binary tree according to [comparator]. |
18 * A [Set] of items stored in a binary tree according to [comparator]. | 18 /// Supports bidirectional iteration. |
19 * Supports bidirectional iteration. | |
20 */ | |
21 abstract class TreeSet<V> extends IterableBase<V> implements Set<V> { | 19 abstract class TreeSet<V> extends IterableBase<V> implements Set<V> { |
22 final Comparator<V> comparator; | 20 final Comparator<V> comparator; |
23 | 21 |
24 int get length; | 22 int get length; |
25 | 23 |
26 /** | 24 /// Create a new [TreeSet] with an ordering defined by [comparator] or the |
27 * Create a new [TreeSet] with an ordering defined by [comparator] or the | 25 /// default `(a, b) => a.compareTo(b)`. |
28 * default `(a, b) => a.compareTo(b)`. | |
29 */ | |
30 factory TreeSet({Comparator<V> comparator}) { | 26 factory TreeSet({Comparator<V> comparator}) { |
31 if (comparator == null) { | 27 comparator ??= (a, b) => (a as dynamic).compareTo(b); |
32 comparator = (a, b) => a.compareTo(b); | |
33 } | |
34 return new AvlTreeSet(comparator: comparator); | 28 return new AvlTreeSet(comparator: comparator); |
35 } | 29 } |
36 | 30 |
37 TreeSet._(this.comparator); | 31 TreeSet._(this.comparator); |
38 | 32 |
39 /** | 33 /// Returns an [BidirectionalIterator] that iterates over this tree. |
40 * Returns an [BidirectionalIterator] that iterates over this tree. | |
41 */ | |
42 BidirectionalIterator<V> get iterator; | 34 BidirectionalIterator<V> get iterator; |
43 | 35 |
44 /** | 36 /// Returns an [BidirectionalIterator] that iterates over this tree, in |
45 * Returns an [BidirectionalIterator] that iterates over this tree, in reverse
. | 37 /// reverse. |
46 */ | |
47 BidirectionalIterator<V> get reverseIterator; | 38 BidirectionalIterator<V> get reverseIterator; |
48 | 39 |
49 /** | 40 /// Returns an [BidirectionalIterator] that starts at [anchor]. By default, |
50 * Returns an [BidirectionalIterator] that starts at [anchor]. | 41 /// the iterator includes the anchor with the first movement; set [inclusive] |
51 * By default, the iterator includes the anchor with the first movement; | 42 /// to false if you want to exclude the anchor. Set [reversed] to true to |
52 * set [inclusive] to false if you want to exclude the anchor. Set [reversed] | 43 /// change the direction of of moveNext and movePrevious. |
53 * to true to change the direction of of moveNext and movePrevious. | 44 /// |
54 * | 45 /// Note: This iterator allows you to walk the entire set. It does not |
55 * Note: This iterator allows you to walk the entire set. It does not present | 46 /// present a subview. |
56 * a subview. | |
57 */ | |
58 BidirectionalIterator<V> fromIterator(V anchor, | 47 BidirectionalIterator<V> fromIterator(V anchor, |
59 {bool reversed: false, bool inclusive: true}); | 48 {bool reversed: false, bool inclusive: true}); |
60 | 49 |
61 /** | 50 /// Search the tree for the matching [object] or the [nearestOption] |
62 * Search the tree for the matching [object] or the [nearestOption] | 51 /// if missing. See [TreeSearch]. |
63 * if missing. See [TreeSearch]. | |
64 */ | |
65 V nearest(V object, {TreeSearch nearestOption: TreeSearch.NEAREST}); | 52 V nearest(V object, {TreeSearch nearestOption: TreeSearch.NEAREST}); |
66 | 53 |
67 // TODO: toString or not toString, that is the question. | 54 // TODO: toString or not toString, that is the question. |
68 } | 55 } |
69 | 56 |
70 /** | 57 /// Controls the results for [TreeSet.searchNearest]() |
71 * Controls the results for [TreeSet.searchNearest]() | 58 enum TreeSearch { |
72 */ | 59 /// If result not found, always chose the smaller element |
73 class TreeSearch { | 60 LESS_THAN, |
74 | 61 |
75 /** | 62 /// If result not found, chose the nearest based on comparison |
76 * If result not found, always chose the smaler element | 63 NEAREST, |
77 */ | |
78 static const LESS_THAN = const TreeSearch._(1); | |
79 | 64 |
80 /** | 65 /// If result not found, always chose the greater element |
81 * If result not found, chose the nearest based on comparison | 66 GREATER_THAN |
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 } | 67 } |
93 | 68 |
94 /** | 69 /// A node in the [TreeSet]. |
95 * A node in the [TreeSet]. | |
96 */ | |
97 abstract class _TreeNode<V> { | 70 abstract class _TreeNode<V> { |
98 _TreeNode<V> get left; | 71 _TreeNode<V> get left; |
99 _TreeNode<V> get right; | 72 _TreeNode<V> get right; |
100 | 73 |
101 //TODO(codefu): Remove need for [parent]; this is just an implementation note | 74 //TODO(codefu): Remove need for [parent]; this is just an implementation note |
102 _TreeNode<V> get parent; | 75 _TreeNode<V> get parent; |
103 V object; | 76 V object; |
104 | 77 |
105 /** | 78 /// TreeNodes are always allocated as leafs. |
106 * TreeNodes are always allocated as leafs. | |
107 */ | |
108 _TreeNode({this.object}); | 79 _TreeNode({this.object}); |
109 | 80 |
110 /** | 81 /// Return the minimum node for the subtree |
111 * Return the minimum node for the subtree | |
112 */ | |
113 _TreeNode<V> get minimumNode { | 82 _TreeNode<V> get minimumNode { |
114 var node = this; | 83 var node = this; |
115 while (node.left != null) { | 84 while (node.left != null) { |
116 node = node.left; | 85 node = node.left; |
117 } | 86 } |
118 return node; | 87 return node; |
119 } | 88 } |
120 | 89 |
121 /** | 90 /// Return the maximum node for the subtree |
122 * Return the maximum node for the subtree | |
123 */ | |
124 _TreeNode<V> get maximumNode { | 91 _TreeNode<V> get maximumNode { |
125 var node = this; | 92 var node = this; |
126 while (node.right != null) { | 93 while (node.right != null) { |
127 node = node.right; | 94 node = node.right; |
128 } | 95 } |
129 return node; | 96 return node; |
130 } | 97 } |
131 | 98 |
132 /** | 99 /// Return the next greatest element (or null) |
133 * Return the next greatest element (or null) | |
134 */ | |
135 _TreeNode<V> get successor { | 100 _TreeNode<V> get successor { |
136 var node = this; | 101 var node = this; |
137 if (node.right != null) { | 102 if (node.right != null) { |
138 return node.right.minimumNode; | 103 return node.right.minimumNode; |
139 } | 104 } |
140 while (node.parent != null && node == node.parent.right) { | 105 while (node.parent != null && node == node.parent.right) { |
141 node = node.parent; | 106 node = node.parent; |
142 } | 107 } |
143 return node.parent; | 108 return node.parent; |
144 } | 109 } |
145 | 110 |
146 /** | 111 /// Return the next smaller element (or null) |
147 * Return the next smaller element (or null) | |
148 */ | |
149 _TreeNode<V> get predecessor { | 112 _TreeNode<V> get predecessor { |
150 var node = this; | 113 var node = this; |
151 if (node.left != null) { | 114 if (node.left != null) { |
152 return node.left.maximumNode; | 115 return node.left.maximumNode; |
153 } | 116 } |
154 while (node.parent != null && node.parent._left == node) { | 117 while (node.parent != null && node.parent.left == node) { |
155 node = node.parent; | 118 node = node.parent; |
156 } | 119 } |
157 return node.parent; | 120 return node.parent; |
158 } | 121 } |
159 } | 122 } |
160 | 123 |
161 /** | 124 /// AVL implementation of a self-balancing binary tree. Optimized for lookup |
162 * AVL implementation of a self-balancing binary tree. Optimized for lookup | 125 /// operations. |
163 * operations. | 126 /// |
164 * | 127 /// Notes: Adapted from "Introduction to Algorithms", second edition, |
165 * Notes: Adapted from "Introduction to Algorithms", second edition, | 128 /// by Thomas H. Cormen, Charles E. Leiserson, |
166 * by Thomas H. Cormen, Charles E. Leiserson, | 129 /// Ronald L. Rivest, Clifford Stein. |
167 * Ronald L. Rivest, Clifford Stein. | 130 /// chapter 13.2 |
168 * chapter 13.2 | |
169 */ | |
170 class AvlTreeSet<V> extends TreeSet<V> { | 131 class AvlTreeSet<V> extends TreeSet<V> { |
171 int _length = 0; | 132 int _length = 0; |
172 AvlNode<V> _root; | 133 AvlNode<V> _root; |
173 // Modification count to the tree, monotonically increasing | 134 // Modification count to the tree, monotonically increasing |
174 int _modCount = 0; | 135 int _modCount = 0; |
175 | 136 |
176 int get length => _length; | 137 int get length => _length; |
177 | 138 |
178 AvlTreeSet({Comparator<V> comparator}) : super._(comparator); | 139 AvlTreeSet({Comparator<V> comparator}) : super._(comparator); |
179 | 140 |
180 /** | 141 /// Add the element to the tree. |
181 * Add the element to the tree. | |
182 */ | |
183 bool add(V element) { | 142 bool add(V element) { |
184 if (_root == null) { | 143 if (_root == null) { |
185 AvlNode<V> node = new AvlNode<V>(object: element); | 144 AvlNode<V> node = new AvlNode<V>(object: element); |
186 _root = node; | 145 _root = node; |
187 ++_length; | 146 ++_length; |
188 ++_modCount; | 147 ++_modCount; |
189 return true; | 148 return true; |
190 } | 149 } |
191 | 150 |
192 AvlNode<V> x = _root; | 151 AvlNode<V> x = _root; |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
283 } | 242 } |
284 node._balanceFactor = 0; | 243 node._balanceFactor = 0; |
285 } | 244 } |
286 break; // out of loop, we're balanced | 245 break; // out of loop, we're balanced |
287 } | 246 } |
288 } // end of while (balancing) | 247 } // end of while (balancing) |
289 _length++; | 248 _length++; |
290 return true; | 249 return true; |
291 } | 250 } |
292 | 251 |
293 /** | 252 /// Test to see if an element is stored in the tree |
294 * Test to see if an element is stored in the tree | |
295 */ | |
296 AvlNode<V> _getNode(V element) { | 253 AvlNode<V> _getNode(V element) { |
297 if (element == null) return null; | 254 if (element == null) return null; |
298 AvlNode<V> x = _root; | 255 AvlNode<V> x = _root; |
299 while (x != null) { | 256 while (x != null) { |
300 int compare = comparator(element, x.object); | 257 int compare = comparator(element, x.object); |
301 if (compare == 0) { | 258 if (compare == 0) { |
302 // This only means our node matches; we need to search for the exact | 259 // 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. | 260 // element. We could have been glutons and used a hashmap to back. |
304 return x; | 261 return x; |
305 } else if (compare < 0) { | 262 } else if (compare < 0) { |
306 x = x.left; | 263 x = x.left; |
307 } else { | 264 } else { |
308 x = x.right; | 265 x = x.right; |
309 } | 266 } |
310 } | 267 } |
311 return null; | 268 return null; |
312 } | 269 } |
313 | 270 |
314 /** | 271 /// This function will right rotate/pivot N with its left child, placing |
315 * This function will right rotate/pivot N with its left child, placing | 272 /// it on the right of its left child. |
316 * it on the right of its left child. | 273 /// |
317 * | 274 /// N Y |
318 * N Y | 275 /// / \ / \ |
319 * / \ / \ | 276 /// Y A Z N |
320 * Y A Z N | 277 /// / \ ==> / \ / \ |
321 * / \ ==> / \ / \ | 278 /// Z B D CB A |
322 * Z B D CB A | 279 /// / \ |
323 * / \ | 280 /// D C |
324 *D C | 281 /// |
325 * | 282 /// Assertion: must have a left element |
326 * Assertion: must have a left element | |
327 */ | |
328 void _rotateRight(AvlNode<V> node) { | 283 void _rotateRight(AvlNode<V> node) { |
329 AvlNode<V> y = node.left; | 284 AvlNode<V> y = node.left; |
330 if (y == null) throw new AssertionError(); | 285 if (y == null) throw new AssertionError(); |
331 | 286 |
332 // turn Y's right subtree(B) into N's left subtree. | 287 // turn Y's right subtree(B) into N's left subtree. |
333 node._left = y.right; | 288 node._left = y.right; |
334 if (node.left != null) { | 289 if (node.left != null) { |
335 node.left._parent = node; | 290 node.left._parent = node; |
336 } | 291 } |
337 y._parent = node.parent; | 292 y._parent = node.parent; |
338 if (y._parent == null) { | 293 if (y._parent == null) { |
339 _root = y; | 294 _root = y; |
340 } else { | 295 } else { |
341 if (node.parent._left == node) { | 296 if (node.parent._left == node) { |
342 node.parent._left = y; | 297 node.parent._left = y; |
343 } else { | 298 } else { |
344 node.parent._right = y; | 299 node.parent._right = y; |
345 } | 300 } |
346 } | 301 } |
347 y._right = node; | 302 y._right = node; |
348 node._parent = y; | 303 node._parent = y; |
349 } | 304 } |
350 | 305 |
351 /** | 306 /// This function will left rotate/pivot N with its right child, placing |
352 * This function will left rotate/pivot N with its right child, placing | 307 /// it on the left of its right child. |
353 * it on the left of its right child. | 308 /// |
354 * | 309 /// N Y |
355 * N Y | 310 /// / \ / \ |
356 * / \ / \ | 311 /// A Y N Z |
357 * A Y N Z | 312 /// / \ ==> / \ / \ |
358 * / \ ==> / \ / \ | 313 /// B Z A BC D |
359 * B Z A BC D | 314 /// / \ |
360 * / \ | 315 /// C D |
361 * C D | 316 /// |
362 * | 317 /// Assertion: must have a right element |
363 * Assertion: must have a right element | |
364 */ | |
365 void _rotateLeft(AvlNode<V> node) { | 318 void _rotateLeft(AvlNode<V> node) { |
366 AvlNode<V> y = node.right; | 319 AvlNode<V> y = node.right; |
367 if (y == null) throw new AssertionError(); | 320 if (y == null) throw new AssertionError(); |
368 | 321 |
369 // turn Y's left subtree(B) into N's right subtree. | 322 // turn Y's left subtree(B) into N's right subtree. |
370 node._right = y.left; | 323 node._right = y.left; |
371 if (node.right != null) { | 324 if (node.right != null) { |
372 node.right._parent = node; | 325 node.right._parent = node; |
373 } | 326 } |
374 y._parent = node.parent; | 327 y._parent = node.parent; |
375 if (y._parent == null) { | 328 if (y._parent == null) { |
376 _root = y; | 329 _root = y; |
377 } else { | 330 } else { |
378 if (node.parent._left == node) { | 331 if (node.parent._left == node) { |
379 y.parent._left = y; | 332 y.parent._left = y; |
380 } else { | 333 } else { |
381 y.parent._right = y; | 334 y.parent._right = y; |
382 } | 335 } |
383 } | 336 } |
384 y._left = node; | 337 y._left = node; |
385 node._parent = y; | 338 node._parent = y; |
386 } | 339 } |
387 | 340 |
388 /** | 341 /// This function will double rotate node with right/left operations. |
389 * This function will double rotate node with right/left operations. | 342 /// node is S. |
390 * node is S. | 343 /// |
391 * | 344 /// S G |
392 * S G | 345 /// / \ / \ |
393 * / \ / \ | 346 /// A C S C |
394 * A C S C | 347 /// / \ ==> / \ / \ |
395 * / \ ==> / \ / \ | 348 /// G B A DC B |
396 * G B A DC B | 349 /// / \ |
397 * / \ | 350 /// D C |
398 * D C | |
399 */ | |
400 void _rotateRightLeft(AvlNode<V> node) { | 351 void _rotateRightLeft(AvlNode<V> node) { |
401 _rotateRight(node.right); | 352 _rotateRight(node.right); |
402 _rotateLeft(node); | 353 _rotateLeft(node); |
403 } | 354 } |
404 | 355 |
405 /** | 356 /// This function will double rotate node with left/right operations. |
406 * This function will double rotate node with left/right operations. | 357 /// node is S. |
407 * node is S. | 358 /// |
408 * | 359 /// S G |
409 * S G | 360 /// / \ / \ |
410 * / \ / \ | 361 /// C A C S |
411 * C A C S | 362 /// / \ ==> / \ / \ |
412 * / \ ==> / \ / \ | 363 /// B G B CD A |
413 *B G B CD A | 364 /// / \ |
414 * / \ | 365 /// C D |
415 * C D | |
416 */ | |
417 void _rotateLeftRight(AvlNode<V> node) { | 366 void _rotateLeftRight(AvlNode<V> node) { |
418 _rotateLeft(node.left); | 367 _rotateLeft(node.left); |
419 _rotateRight(node); | 368 _rotateRight(node); |
420 } | 369 } |
421 | 370 |
422 bool addAll(Iterable<V> items) { | 371 bool addAll(Iterable<V> items) { |
423 bool modified = false; | 372 bool modified = false; |
424 for (V ele in items) { | 373 for (V ele in items) { |
425 modified = add(ele) ? true : modified; | 374 modified = add(ele) ? true : modified; |
426 } | 375 } |
427 return modified; | 376 return modified; |
428 } | 377 } |
429 | 378 |
430 void clear() { | 379 void clear() { |
431 _length = 0; | 380 _length = 0; |
432 _root = null; | 381 _root = null; |
433 ++_modCount; | 382 ++_modCount; |
434 } | 383 } |
435 | 384 |
436 bool containsAll(Iterable<Object> items) { | 385 bool containsAll(Iterable<Object> items) { |
437 for (var ele in items) { | 386 for (var ele in items) { |
438 if (!contains(ele)) return false; | 387 if (!contains(ele)) return false; |
439 } | 388 } |
440 return true; | 389 return true; |
441 } | 390 } |
442 | 391 |
443 bool remove(Object item) { | 392 bool remove(Object item) { |
444 AvlNode<V> x = _getNode(item); | 393 if (item is! V) return false; |
| 394 |
| 395 AvlNode<V> x = _getNode(item as V); |
445 if (x != null) { | 396 if (x != null) { |
446 _removeNode(x); | 397 _removeNode(x); |
447 return true; | 398 return true; |
448 } | 399 } |
449 return false; | 400 return false; |
450 } | 401 } |
451 | 402 |
452 void _removeNode(AvlNode<V> node) { | 403 void _removeNode(AvlNode<V> node) { |
453 AvlNode<V> y, w; | 404 AvlNode<V> y, w; |
454 | 405 |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
610 if (node.parent.left == node) { | 561 if (node.parent.left == node) { |
611 node.parent._balanceFactor += 1; | 562 node.parent._balanceFactor += 1; |
612 } else { | 563 } else { |
613 node.parent._balanceFactor -= 1; | 564 node.parent._balanceFactor -= 1; |
614 } | 565 } |
615 } | 566 } |
616 node = node.parent; | 567 node = node.parent; |
617 } | 568 } |
618 } | 569 } |
619 | 570 |
620 /** | 571 /// See [Set.removeAll] |
621 * See [Set.removeAll] | |
622 */ | |
623 void removeAll(Iterable items) { | 572 void removeAll(Iterable items) { |
624 for (var ele in items) { | 573 for (var ele in items) { |
625 remove(ele); | 574 remove(ele); |
626 } | 575 } |
627 } | 576 } |
628 | 577 |
629 /** | 578 /// See [Set.retainAll] |
630 * See [Set.retainAll] | |
631 */ | |
632 void retainAll(Iterable<Object> elements) { | 579 void retainAll(Iterable<Object> elements) { |
633 List<V> chosen = []; | 580 List<V> chosen = <V>[]; |
634 for (var target in elements) { | 581 for (var target in elements) { |
635 if (contains(target)) { | 582 if (target is V && contains(target)) { |
636 chosen.add(target); | 583 chosen.add(target); |
637 } | 584 } |
638 } | 585 } |
639 clear(); | 586 clear(); |
640 addAll(chosen); | 587 addAll(chosen); |
641 } | 588 } |
642 | 589 |
643 /** | 590 /// See [Set.retainWhere] |
644 * See [Set.retainWhere] | |
645 */ | |
646 void retainWhere(bool test(V element)) { | 591 void retainWhere(bool test(V element)) { |
647 List<V> chosen = []; | 592 List<V> chosen = []; |
648 for (var target in this) { | 593 for (var target in this) { |
649 if (test(target)) { | 594 if (test(target)) { |
650 chosen.add(target); | 595 chosen.add(target); |
651 } | 596 } |
652 } | 597 } |
653 clear(); | 598 clear(); |
654 addAll(chosen); | 599 addAll(chosen); |
655 } | 600 } |
656 | 601 |
657 /** | 602 /// See [Set.removeWhere] |
658 * See [Set.removeWhere] | |
659 */ | |
660 void removeWhere(bool test(V element)) { | 603 void removeWhere(bool test(V element)) { |
661 List<V> damned = []; | 604 List<V> damned = []; |
662 for (var target in this) { | 605 for (var target in this) { |
663 if (test(target)) { | 606 if (test(target)) { |
664 damned.add(target); | 607 damned.add(target); |
665 } | 608 } |
666 } | 609 } |
667 removeAll(damned); | 610 removeAll(damned); |
668 } | 611 } |
669 | 612 |
670 /** | 613 /// See [IterableBase.first] |
671 * See [IterableBase.first] | |
672 */ | |
673 V get first { | 614 V get first { |
674 if (_root == null) return null; | 615 if (_root == null) return null; |
675 AvlNode<V> min = _root.minimumNode; | 616 AvlNode<V> min = _root.minimumNode; |
676 return min != null ? min.object : null; | 617 return min != null ? min.object : null; |
677 } | 618 } |
678 | 619 |
679 /** | 620 /// See [IterableBase.last] |
680 * See [IterableBase.last] | |
681 */ | |
682 V get last { | 621 V get last { |
683 if (_root == null) return null; | 622 if (_root == null) return null; |
684 AvlNode<V> max = _root.maximumNode; | 623 AvlNode<V> max = _root.maximumNode; |
685 return max != null ? max.object : null; | 624 return max != null ? max.object : null; |
686 } | 625 } |
687 | 626 |
688 /** | 627 /// See [Set.lookup] |
689 * See [Set.lookup] | |
690 */ | |
691 V lookup(Object element) { | 628 V lookup(Object element) { |
692 if (element == null || _root == null) return null; | 629 if (element is! V || _root == null) return null; |
693 AvlNode<V> x = _root; | 630 AvlNode<V> x = _root; |
694 int compare = 0; | 631 int compare = 0; |
695 while (x != null) { | 632 while (x != null) { |
696 compare = comparator(element, x.object); | 633 compare = comparator(element as V, x.object); |
697 if (compare == 0) { | 634 if (compare == 0) { |
698 return x.object; | 635 return x.object; |
699 } else if (compare < 0) { | 636 } else if (compare < 0) { |
700 x = x.left; | 637 x = x.left; |
701 } else { | 638 } else { |
702 x = x.right; | 639 x = x.right; |
703 } | 640 } |
704 } | 641 } |
705 return null; | 642 return null; |
706 } | 643 } |
707 | 644 |
708 V nearest(V object, {TreeSearch nearestOption: TreeSearch.NEAREST}) { | 645 V nearest(V object, {TreeSearch nearestOption: TreeSearch.NEAREST}) { |
709 AvlNode<V> found = _searchNearest(object, option: nearestOption); | 646 AvlNode<V> found = _searchNearest(object, option: nearestOption); |
710 return (found != null) ? found.object : null; | 647 return (found != null) ? found.object : null; |
711 } | 648 } |
712 | 649 |
713 /** | 650 /// Search the tree for the matching element, or the 'nearest' node. |
714 * Search the tree for the matching element, or the 'nearest' node. | 651 /// NOTE: [BinaryTree.comparator] needs to have finer granulatity than -1,0,1 |
715 * NOTE: [BinaryTree.comparator] needs to have finer granulatity than -1,0,1 | 652 /// in order for this to return something that's meaningful. |
716 * in order for this to return something that's meaningful. | |
717 */ | |
718 AvlNode<V> _searchNearest(V element, | 653 AvlNode<V> _searchNearest(V element, |
719 {TreeSearch option: TreeSearch.NEAREST}) { | 654 {TreeSearch option: TreeSearch.NEAREST}) { |
720 if (element == null || _root == null) { | 655 if (element == null || _root == null) { |
721 return null; | 656 return null; |
722 } | 657 } |
723 AvlNode<V> x = _root; | 658 AvlNode<V> x = _root; |
724 AvlNode<V> previous; | 659 AvlNode<V> previous; |
725 int compare = 0; | 660 int compare = 0; |
726 while (x != null) { | 661 while (x != null) { |
727 previous = x; | 662 previous = x; |
(...skipping 23 matching lines...) Expand all Loading... |
751 if (compare < 0) { | 686 if (compare < 0) { |
752 return compare.abs() < otherCompare ? previous : x; | 687 return compare.abs() < otherCompare ? previous : x; |
753 } | 688 } |
754 return otherCompare.abs() < compare ? x : previous; | 689 return otherCompare.abs() < compare ? x : previous; |
755 } | 690 } |
756 | 691 |
757 // | 692 // |
758 // [IterableBase]<V> Methods | 693 // [IterableBase]<V> Methods |
759 // | 694 // |
760 | 695 |
761 /** | 696 /// See [IterableBase.iterator] |
762 * See [IterableBase.iterator] | |
763 */ | |
764 BidirectionalIterator<V> get iterator => new _AvlTreeIterator._(this); | 697 BidirectionalIterator<V> get iterator => new _AvlTreeIterator._(this); |
765 | 698 |
766 /** | 699 /// See [TreeSet.reverseIterator] |
767 * See [TreeSet.reverseIterator] | |
768 */ | |
769 BidirectionalIterator<V> get reverseIterator => | 700 BidirectionalIterator<V> get reverseIterator => |
770 new _AvlTreeIterator._(this, reversed: true); | 701 new _AvlTreeIterator._(this, reversed: true); |
771 | 702 |
772 /** | 703 /// See [TreeSet.fromIterator] |
773 * See [TreeSet.fromIterator] | |
774 */ | |
775 BidirectionalIterator<V> fromIterator(V anchor, | 704 BidirectionalIterator<V> fromIterator(V anchor, |
776 {bool reversed: false, bool inclusive: true}) => | 705 {bool reversed: false, bool inclusive: true}) => |
777 new _AvlTreeIterator<V>._(this, | 706 new _AvlTreeIterator<V>._(this, |
778 anchorObject: anchor, reversed: reversed, inclusive: inclusive); | 707 anchorObject: anchor, reversed: reversed, inclusive: inclusive); |
779 | 708 |
780 /** | 709 /// See [IterableBase.contains] |
781 * See [IterableBase.contains] | |
782 */ | |
783 bool contains(Object object) { | 710 bool contains(Object object) { |
784 AvlNode<V> x = _getNode(object as V); | 711 AvlNode<V> x = _getNode(object as V); |
785 return x != null; | 712 return x != null; |
786 } | 713 } |
787 | 714 |
788 // | 715 // |
789 // [Set] methods | 716 // [Set] methods |
790 // | 717 // |
791 | 718 |
792 /** | 719 /// See [Set.intersection] |
793 * See [Set.intersection] | |
794 */ | |
795 Set<V> intersection(Set<Object> other) { | 720 Set<V> intersection(Set<Object> other) { |
796 TreeSet<V> set = new TreeSet(comparator: comparator); | 721 TreeSet<V> set = new TreeSet(comparator: comparator); |
797 | 722 |
798 // Opitimized for sorted sets | 723 // Optimized for sorted sets |
799 if (other is TreeSet) { | 724 if (other is TreeSet<V>) { |
800 var i1 = iterator; | 725 var i1 = iterator; |
801 var i2 = other.iterator; | 726 var i2 = other.iterator; |
802 var hasMore1 = i1.moveNext(); | 727 var hasMore1 = i1.moveNext(); |
803 var hasMore2 = i2.moveNext(); | 728 var hasMore2 = i2.moveNext(); |
804 while (hasMore1 && hasMore2) { | 729 while (hasMore1 && hasMore2) { |
805 var c = comparator(i1.current, i2.current); | 730 var c = comparator(i1.current, i2.current); |
806 if (c == 0) { | 731 if (c == 0) { |
807 set.add(i1.current); | 732 set.add(i1.current); |
808 hasMore1 = i1.moveNext(); | 733 hasMore1 = i1.moveNext(); |
809 hasMore2 = i2.moveNext(); | 734 hasMore2 = i2.moveNext(); |
810 } else if (c < 0) { | 735 } else if (c < 0) { |
811 hasMore1 = i1.moveNext(); | 736 hasMore1 = i1.moveNext(); |
812 } else { | 737 } else { |
813 hasMore2 = i2.moveNext(); | 738 hasMore2 = i2.moveNext(); |
814 } | 739 } |
815 } | 740 } |
816 return set; | 741 return set; |
817 } | 742 } |
818 | 743 |
819 // Non-optimized version. | 744 // Non-optimized version. |
820 for (var target in this) { | 745 for (var target in this) { |
821 if (other.contains(target)) { | 746 if (other.contains(target)) { |
822 set.add(target); | 747 set.add(target); |
823 } | 748 } |
824 } | 749 } |
825 return set; | 750 return set; |
826 } | 751 } |
827 | 752 |
828 /** | 753 /// See [Set.union] |
829 * See [Set.union] | |
830 */ | |
831 Set<V> union(Set<V> other) { | 754 Set<V> union(Set<V> other) { |
832 TreeSet<V> set = new TreeSet(comparator: comparator); | 755 TreeSet<V> set = new TreeSet(comparator: comparator); |
833 | 756 |
834 if (other is TreeSet) { | 757 if (other is TreeSet) { |
835 var i1 = iterator; | 758 var i1 = iterator; |
836 var i2 = other.iterator; | 759 var i2 = other.iterator; |
837 var hasMore1 = i1.moveNext(); | 760 var hasMore1 = i1.moveNext(); |
838 var hasMore2 = i2.moveNext(); | 761 var hasMore2 = i2.moveNext(); |
839 while (hasMore1 && hasMore2) { | 762 while (hasMore1 && hasMore2) { |
840 var c = comparator(i1.current, i2.current); | 763 var c = comparator(i1.current, i2.current); |
(...skipping 12 matching lines...) Expand all Loading... |
853 if (hasMore1 || hasMore2) { | 776 if (hasMore1 || hasMore2) { |
854 i1 = hasMore1 ? i1 : i2; | 777 i1 = hasMore1 ? i1 : i2; |
855 do { | 778 do { |
856 set.add(i1.current); | 779 set.add(i1.current); |
857 } while (i1.moveNext()); | 780 } while (i1.moveNext()); |
858 } | 781 } |
859 return set; | 782 return set; |
860 } | 783 } |
861 | 784 |
862 // Non-optimized version. | 785 // Non-optimized version. |
863 return set | 786 return set..addAll(this)..addAll(other); |
864 ..addAll(this) | |
865 ..addAll(other); | |
866 } | 787 } |
867 | 788 |
868 /** | 789 /// See [Set.difference] |
869 * See [Set.difference] | 790 Set<V> difference(Set<Object> other) { |
870 */ | |
871 Set<V> difference(Set<V> other) { | |
872 TreeSet<V> set = new TreeSet(comparator: comparator); | 791 TreeSet<V> set = new TreeSet(comparator: comparator); |
873 | 792 |
874 if (other is TreeSet) { | 793 if (other is TreeSet) { |
875 var i1 = iterator; | 794 var i1 = iterator; |
876 var i2 = other.iterator; | 795 var i2 = other.iterator; |
877 var hasMore1 = i1.moveNext(); | 796 var hasMore1 = i1.moveNext(); |
878 var hasMore2 = i2.moveNext(); | 797 var hasMore2 = i2.moveNext(); |
879 while (hasMore1 && hasMore2) { | 798 while (hasMore1 && hasMore2) { |
880 var c = comparator(i1.current, i2.current); | 799 var c = comparator(i1.current, i2.current); |
881 if (c == 0) { | 800 if (c == 0) { |
(...skipping 16 matching lines...) Expand all Loading... |
898 | 817 |
899 // Non-optimized version. | 818 // Non-optimized version. |
900 for (var target in this) { | 819 for (var target in this) { |
901 if (!other.contains(target)) { | 820 if (!other.contains(target)) { |
902 set.add(target); | 821 set.add(target); |
903 } | 822 } |
904 } | 823 } |
905 return set; | 824 return set; |
906 } | 825 } |
907 | 826 |
908 /** | 827 /// Visible for testing only. |
909 * Visible for testing only. | |
910 */ | |
911 AvlNode<V> getNode(V object) => _getNode(object); | 828 AvlNode<V> getNode(V object) => _getNode(object); |
912 } | 829 } |
913 | 830 |
914 typedef bool _IteratorMove(); | 831 typedef bool _IteratorMove(); |
915 | 832 |
916 /** | 833 /// This iterator either starts at the beginning or end (see [TreeSet.iterator] |
917 * This iterator either starts at the beginning or end (see [TreeSet.iterator] | 834 /// and [TreeSet.reverseIterator]) or from an anchor point in the set (see |
918 * and [TreeSet.reverseIterator]) or from an anchor point in the set (see | 835 /// [TreeSet.fromIterator]). When using fromIterator, the inital anchor point |
919 * [TreeSet.fromIterator]). When using fromIterator, the inital | 836 /// is included in the first movement (either [moveNext] or [movePrevious]) but |
920 * anchor point is included in the first movement (either [moveNext] or | 837 /// can optionally be excluded in the constructor. |
921 * [movePrevious]) but can optionally be excluded in the constructor. | |
922 */ | |
923 class _AvlTreeIterator<V> implements BidirectionalIterator<V> { | 838 class _AvlTreeIterator<V> implements BidirectionalIterator<V> { |
924 static const LEFT = -1; | 839 static const LEFT = -1; |
925 static const WALK = 0; | 840 static const WALK = 0; |
926 static const RIGHT = 1; | 841 static const RIGHT = 1; |
927 | 842 |
928 final bool reversed; | 843 final bool reversed; |
929 final AvlTreeSet<V> tree; | 844 final AvlTreeSet<V> tree; |
930 final int _modCountGuard; | 845 final int _modCountGuard; |
931 final Object anchorObject; | 846 final V anchorObject; |
932 final bool inclusive; | 847 final bool inclusive; |
933 | 848 |
934 _IteratorMove _moveNext; | 849 _IteratorMove _moveNext; |
935 _IteratorMove _movePrevious; | 850 _IteratorMove _movePrevious; |
936 | 851 |
937 int state; | 852 int state; |
938 _TreeNode<V> _current; | 853 _TreeNode<V> _current; |
939 | 854 |
940 _AvlTreeIterator._(AvlTreeSet<V> tree, | 855 _AvlTreeIterator._(AvlTreeSet<V> tree, |
941 {reversed: false, this.inclusive: true, this.anchorObject: null}) | 856 {reversed: false, this.inclusive: true, this.anchorObject: null}) |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1021 default: | 936 default: |
1022 _current = _current.predecessor; | 937 _current = _current.predecessor; |
1023 if (_current == null) { | 938 if (_current == null) { |
1024 state = LEFT; | 939 state = LEFT; |
1025 } | 940 } |
1026 return state == WALK; | 941 return state == WALK; |
1027 } | 942 } |
1028 } | 943 } |
1029 } | 944 } |
1030 | 945 |
1031 /** | 946 /// Private class used to track element insertions in the [TreeSet]. |
1032 * Private class used to track element insertions in the [TreeSet]. | |
1033 */ | |
1034 class AvlNode<V> extends _TreeNode<V> { | 947 class AvlNode<V> extends _TreeNode<V> { |
1035 AvlNode<V> _left; | 948 AvlNode<V> _left; |
1036 AvlNode<V> _right; | 949 AvlNode<V> _right; |
1037 //TODO(codefu): Remove need for [parent]; this is just an implementation note | 950 // TODO(codefu): Remove need for [parent]; this is just an implementation note |
1038 AvlNode<V> _parent; | 951 AvlNode<V> _parent; |
1039 int _balanceFactor = 0; | 952 int _balanceFactor = 0; |
1040 | 953 |
1041 AvlNode<V> get left => _left; | 954 AvlNode<V> get left => _left; |
1042 AvlNode<V> get right => _right; | 955 AvlNode<V> get right => _right; |
1043 AvlNode<V> get parent => _parent; | 956 AvlNode<V> get parent => _parent; |
1044 int get balance => _balanceFactor; | 957 int get balance => _balanceFactor; |
1045 | 958 |
1046 AvlNode({V object}) : super(object: object); | 959 AvlNode({V object}) : super(object: object); |
1047 | 960 |
1048 String toString() => | 961 String toString() => |
1049 "(b:$balance o: $object l:${left != null} r:${right != null})"; | 962 "(b:$balance o: $object l:${left != null} r:${right != null})"; |
1050 } | 963 } |
OLD | NEW |