| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of dart.collection; | 5 part of dart.collection; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * A [Queue] is a collection that can be manipulated at both ends. One | 8 * A [Queue] is a collection that can be manipulated at both ends. One |
| 9 * can iterate over the elements of a queue through [forEach] or with | 9 * can iterate over the elements of a queue through [forEach] or with |
| 10 * an [Iterator]. | 10 * an [Iterator]. |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 94 | 94 |
| 95 /** | 95 /** |
| 96 * An entry in a doubly linked list. It contains a pointer to the next | 96 * An entry in a doubly linked list. It contains a pointer to the next |
| 97 * entry, the previous entry, and the boxed element. | 97 * entry, the previous entry, and the boxed element. |
| 98 */ | 98 */ |
| 99 class DoubleLinkedQueueEntry<E> { | 99 class DoubleLinkedQueueEntry<E> { |
| 100 DoubleLinkedQueueEntry<E> _previous; | 100 DoubleLinkedQueueEntry<E> _previous; |
| 101 DoubleLinkedQueueEntry<E> _next; | 101 DoubleLinkedQueueEntry<E> _next; |
| 102 E _element; | 102 E _element; |
| 103 | 103 |
| 104 DoubleLinkedQueueEntry(E e) { | 104 DoubleLinkedQueueEntry(E e) : _element = e; |
| 105 _element = e; | |
| 106 } | |
| 107 | 105 |
| 108 void _link(DoubleLinkedQueueEntry<E> p, | 106 void _link(DoubleLinkedQueueEntry<E> previous, |
| 109 DoubleLinkedQueueEntry<E> n) { | 107 DoubleLinkedQueueEntry<E> next) { |
| 110 _next = n; | 108 _next = next; |
| 111 _previous = p; | 109 _previous = previous; |
| 112 p._next = this; | 110 previous._next = this; |
| 113 n._previous = this; | 111 next._previous = this; |
| 114 } | 112 } |
| 115 | 113 |
| 116 void append(E e) { | 114 void append(E e) { |
| 117 new DoubleLinkedQueueEntry<E>(e)._link(this, _next); | 115 new DoubleLinkedQueueEntry<E>(e)._link(this, _next); |
| 118 } | 116 } |
| 119 | 117 |
| 120 void prepend(E e) { | 118 void prepend(E e) { |
| 121 new DoubleLinkedQueueEntry<E>(e)._link(_previous, this); | 119 new DoubleLinkedQueueEntry<E>(e)._link(_previous, this); |
| 122 } | 120 } |
| 123 | 121 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 145 return _element; | 143 return _element; |
| 146 } | 144 } |
| 147 | 145 |
| 148 void set element(E e) { | 146 void set element(E e) { |
| 149 _element = e; | 147 _element = e; |
| 150 } | 148 } |
| 151 } | 149 } |
| 152 | 150 |
| 153 /** | 151 /** |
| 154 * A sentinel in a double linked list is used to manipulate the list | 152 * A sentinel in a double linked list is used to manipulate the list |
| 155 * at both ends. A double linked list has exactly one sentinel, which | 153 * at both ends. |
| 156 * is the only entry when the list is constructed. Initially, a | 154 * A double linked list has exactly one sentinel, |
| 157 * sentinel has its next and previous entry point to itself. A | 155 * which is the only entry when the list is constructed. |
| 158 * sentinel does not box any user element. | 156 * Initially, a sentinel has its next and previous entry point to itself. |
| 157 * A sentinel does not box any user element. |
| 159 */ | 158 */ |
| 160 class _DoubleLinkedQueueEntrySentinel<E> extends DoubleLinkedQueueEntry<E> { | 159 class _DoubleLinkedQueueEntrySentinel<E> extends DoubleLinkedQueueEntry<E> { |
| 161 _DoubleLinkedQueueEntrySentinel() : super(null) { | 160 _DoubleLinkedQueueEntrySentinel() : super(null) { |
| 162 _link(this, this); | 161 _link(this, this); |
| 163 } | 162 } |
| 164 | 163 |
| 165 E remove() { | 164 E remove() { |
| 166 throw new StateError("Empty queue"); | 165 throw new StateError("Empty queue"); |
| 167 } | 166 } |
| 168 | 167 |
| 169 DoubleLinkedQueueEntry<E> _asNonSentinelEntry() { | 168 DoubleLinkedQueueEntry<E> _asNonSentinelEntry() { |
| 170 return null; | 169 return null; |
| 171 } | 170 } |
| 172 | 171 |
| 173 void set element(E e) { | 172 void set element(E e) { |
| 174 // This setter is unreachable. | 173 // This setter is unreachable. |
| 174 // TODO(lrn): Don't inherit the field if we don't use it. |
| 175 assert(false); | 175 assert(false); |
| 176 } | 176 } |
| 177 | 177 |
| 178 E get element { | 178 E get element { |
| 179 throw new StateError("Empty queue"); | 179 throw new StateError("Empty queue"); |
| 180 } | 180 } |
| 181 } | 181 } |
| 182 | 182 |
| 183 /** | 183 /** |
| 184 * A [Queue] implementation based on a double-linked list. | 184 * A [Queue] implementation based on a double-linked list. |
| 185 * | 185 * |
| 186 * Allows constant time add, remove-at-ends and peek operations. | 186 * Allows constant time add, remove-at-ends and peek operations. |
| 187 * | |
| 188 * Can do [removeAll] and [retainAll] in linear time. | |
| 189 */ | 187 */ |
| 190 class DoubleLinkedQueue<E> extends IterableBase<E> implements Queue<E> { | 188 class DoubleLinkedQueue<E> extends IterableBase<E> implements Queue<E> { |
| 191 _DoubleLinkedQueueEntrySentinel<E> _sentinel; | 189 _DoubleLinkedQueueEntrySentinel<E> _sentinel; |
| 192 int _elementCount = 0; | 190 int _elementCount = 0; |
| 193 | 191 |
| 194 DoubleLinkedQueue() { | 192 DoubleLinkedQueue() { |
| 195 _sentinel = new _DoubleLinkedQueueEntrySentinel<E>(); | 193 _sentinel = new _DoubleLinkedQueueEntrySentinel<E>(); |
| 196 } | 194 } |
| 197 | 195 |
| 198 factory DoubleLinkedQueue.from(Iterable<E> other) { | 196 factory DoubleLinkedQueue.from(Iterable<E> other) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 233 return result; | 231 return result; |
| 234 } | 232 } |
| 235 | 233 |
| 236 E removeFirst() { | 234 E removeFirst() { |
| 237 E result = _sentinel._next.remove(); | 235 E result = _sentinel._next.remove(); |
| 238 _elementCount--; | 236 _elementCount--; |
| 239 return result; | 237 return result; |
| 240 } | 238 } |
| 241 | 239 |
| 242 bool remove(Object o) { | 240 bool remove(Object o) { |
| 243 DoubleLinkedQueueEntry<E> entry = firstEntry(); | 241 DoubleLinkedQueueEntry<E> entry = _sentinel._next; |
| 244 while (!identical(entry, _sentinel)) { | 242 while (!identical(entry, _sentinel)) { |
| 245 if (entry.element == o) { | 243 if (entry.element == o) { |
| 246 entry.remove(); | 244 entry.remove(); |
| 247 _elementCount--; | 245 _elementCount--; |
| 248 return true; | 246 return true; |
| 249 } | 247 } |
| 250 entry = entry._next; | 248 entry = entry._next; |
| 251 } | 249 } |
| 252 return false; | 250 return false; |
| 253 } | 251 } |
| 254 | 252 |
| 255 void _filter(bool test(E element), bool removeMatching) { | 253 void _filter(bool test(E element), bool removeMatching) { |
| 256 DoubleLinkedQueueEntry<E> entry = firstEntry(); | 254 DoubleLinkedQueueEntry<E> entry = _sentinel._next; |
| 257 while (!identical(entry, _sentinel)) { | 255 while (!identical(entry, _sentinel)) { |
| 258 DoubleLinkedQueueEntry<E> next = entry._next; | 256 DoubleLinkedQueueEntry<E> next = entry._next; |
| 259 if (identical(removeMatching, test(entry.element))) { | 257 if (identical(removeMatching, test(entry.element))) { |
| 260 entry.remove(); | 258 entry.remove(); |
| 261 _elementCount--; | 259 _elementCount--; |
| 262 } | 260 } |
| 263 entry = next; | 261 entry = next; |
| 264 } | 262 } |
| 265 } | 263 } |
| 266 | 264 |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 347 } | 345 } |
| 348 | 346 |
| 349 /** | 347 /** |
| 350 * List based [Queue]. | 348 * List based [Queue]. |
| 351 * | 349 * |
| 352 * Keeps a cyclic buffer of elements, and grows to a larger buffer when | 350 * Keeps a cyclic buffer of elements, and grows to a larger buffer when |
| 353 * it fills up. This guarantees constant time peek and remove operations, and | 351 * it fills up. This guarantees constant time peek and remove operations, and |
| 354 * amortized constant time add operations. | 352 * amortized constant time add operations. |
| 355 * | 353 * |
| 356 * The structure is efficient for any queue or stack usage. | 354 * The structure is efficient for any queue or stack usage. |
| 357 * | |
| 358 * Operations like [removeAll] and [removeWhere] are very | |
| 359 * inefficient. If those are needed, use a [DoubleLinkedQueue] instead. | |
| 360 */ | 355 */ |
| 361 class ListQueue<E> extends IterableBase<E> implements Queue<E> { | 356 class ListQueue<E> extends IterableBase<E> implements Queue<E> { |
| 362 static const int _INITIAL_CAPACITY = 8; | 357 static const int _INITIAL_CAPACITY = 8; |
| 363 List<E> _table; | 358 List<E> _table; |
| 364 int _head; | 359 int _head; |
| 365 int _tail; | 360 int _tail; |
| 366 int _modificationCount = 0; | 361 int _modificationCount = 0; |
| 367 | 362 |
| 368 /** | 363 /** |
| 369 * Create an empty queue. | 364 * Create an empty queue. |
| (...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 712 _queue._checkModification(_modificationCount); | 707 _queue._checkModification(_modificationCount); |
| 713 if (_position == _end) { | 708 if (_position == _end) { |
| 714 _current = null; | 709 _current = null; |
| 715 return false; | 710 return false; |
| 716 } | 711 } |
| 717 _current = _queue._table[_position]; | 712 _current = _queue._table[_position]; |
| 718 _position = (_position + 1) & (_queue._table.length - 1); | 713 _position = (_position + 1) & (_queue._table.length - 1); |
| 719 return true; | 714 return true; |
| 720 } | 715 } |
| 721 } | 716 } |
| OLD | NEW |