| 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 |