| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 library dart.pkg.collection.priority_queue; | 5 import "dart:collection"; |
| 6 | 6 |
| 7 import "dart:collection" show SplayTreeSet; | 7 /// A priority queue is a priority based work-list of elements. |
| 8 | 8 /// |
| 9 /** | 9 /// The queue allows adding elements, and removing them again in priority order. |
| 10 * A priority queue is a priority based work-list of elements. | |
| 11 * | |
| 12 * The queue allows adding elements, and removing them again in priority order. | |
| 13 */ | |
| 14 abstract class PriorityQueue<E> { | 10 abstract class PriorityQueue<E> { |
| 15 /** | 11 /// Creates an empty [PriorityQueue]. |
| 16 * Creates an empty [PriorityQueue]. | 12 /// |
| 17 * | 13 /// The created [PriorityQueue] is a plain [HeapPriorityQueue]. |
| 18 * The created [PriorityQueue] is a plain [HeapPriorityQueue]. | 14 /// |
| 19 * | 15 /// The [comparison] is a [Comparator] used to compare the priority of |
| 20 * The [comparison] is a [Comparator] used to compare the priority of | 16 /// elements. An element that compares as less than another element has |
| 21 * elements. An element that compares as less than another element has | 17 /// a higher priority. |
| 22 * a higher priority. | 18 /// |
| 23 * | 19 /// If [comparison] is omitted, it defaults to [Comparable.compare]. |
| 24 * If [comparison] is omitted, it defaults to [Comparable.compare]. | |
| 25 */ | |
| 26 factory PriorityQueue([int comparison(E e1, E e2)]) = HeapPriorityQueue<E>; | 20 factory PriorityQueue([int comparison(E e1, E e2)]) = HeapPriorityQueue<E>; |
| 27 | 21 |
| 28 /** | 22 /// Number of elements in the queue. |
| 29 * Number of elements in the queue. | |
| 30 */ | |
| 31 int get length; | 23 int get length; |
| 32 | 24 |
| 33 /** | 25 /// Whether the queue is empty. |
| 34 * Whether the queue is empty. | |
| 35 */ | |
| 36 bool get isEmpty; | 26 bool get isEmpty; |
| 37 | 27 |
| 38 /** | 28 /// Whether the queue has any elements. |
| 39 * Whether the queue has any elements. | |
| 40 */ | |
| 41 bool get isNotEmpty; | 29 bool get isNotEmpty; |
| 42 | 30 |
| 43 /** | 31 /// Checks if [object] is in the queue. |
| 44 * Checks if [object] is in the queue. | 32 /// |
| 45 * | 33 /// Returns true if the element is found. |
| 46 * Returns true if the element is found. | |
| 47 */ | |
| 48 bool contains(E object); | 34 bool contains(E object); |
| 49 | 35 |
| 50 /** | 36 /// Adds element to the queue. |
| 51 * Adds element to the queue. | 37 /// |
| 52 * | 38 /// The element will become the next to be removed by [removeFirst] |
| 53 * The element will become the next to be removed by [removeFirst] | 39 /// when all elements with higher priority have been removed. |
| 54 * when all elements with higher priority have been removed. | |
| 55 */ | |
| 56 void add(E element); | 40 void add(E element); |
| 57 | 41 |
| 58 /** | 42 /// Adds all [elements] to the queue. |
| 59 * Adds all [elements] to the queue. | |
| 60 */ | |
| 61 void addAll(Iterable<E> elements); | 43 void addAll(Iterable<E> elements); |
| 62 | 44 |
| 63 /** | 45 /// Returns the next element that will be returned by [removeFirst]. |
| 64 * Returns the next element that will be returned by [removeFirst]. | 46 /// |
| 65 * | 47 /// The element is not removed from the queue. |
| 66 * The element is not removed from the queue. | 48 /// |
| 67 * | 49 /// The queue must not be empty when this method is called. |
| 68 * The queue must not be empty when this method is called. | |
| 69 */ | |
| 70 E get first; | 50 E get first; |
| 71 | 51 |
| 72 /** | 52 /// Removes and returns the element with the highest priority. |
| 73 * Removes and returns the element with the highest priority. | 53 /// |
| 74 * | 54 /// Repeatedly calling this method, without adding element in between, |
| 75 * Repeatedly calling this method, without adding element in between, | 55 /// is guaranteed to return elements in non-decreasing order as, specified by |
| 76 * is guaranteed to return elements in non-decreasing order as, specified by | 56 /// [comparison]. |
| 77 * [comparison]. | 57 /// |
| 78 * | 58 /// The queue must not be empty when this method is called. |
| 79 * The queue must not be empty when this method is called. | |
| 80 */ | |
| 81 E removeFirst(); | 59 E removeFirst(); |
| 82 | 60 |
| 83 /** | 61 /// Removes an element that compares equal to [element] in the queue. |
| 84 * Removes an element that compares equal to [element] in the queue. | 62 /// |
| 85 * | 63 /// Returns true if an element is found and removed, |
| 86 * Returns true if an element is found and removed, | 64 /// and false if no equal element is found. |
| 87 * and false if no equal element is found. | |
| 88 */ | |
| 89 bool remove(E element); | 65 bool remove(E element); |
| 90 | 66 |
| 91 /** | 67 /// Removes all the elements from this queue and returns them. |
| 92 * Removes all the elements from this queue and returns them. | 68 /// |
| 93 * | 69 /// The returned iterable has no specified order. |
| 94 * The returned iterable has no specified order. | |
| 95 */ | |
| 96 Iterable<E> removeAll(); | 70 Iterable<E> removeAll(); |
| 97 | 71 |
| 98 /** | 72 /// Removes all the elements from this queue. |
| 99 * Removes all the elements from this queue. | |
| 100 */ | |
| 101 void clear(); | 73 void clear(); |
| 102 | 74 |
| 103 /** | 75 /// Returns a list of the elements of this queue in priority order. |
| 104 * Returns a list of the elements of this queue in priority order. | 76 /// |
| 105 * | 77 /// The queue is not modified. |
| 106 * The queue is not modified. | 78 /// |
| 107 * | 79 /// The order is the order that the elements would be in if they were |
| 108 * The order is the order that the elements would be in if they were | 80 /// removed from this queue using [removeFirst]. |
| 109 * removed from this queue using [removeFirst]. | |
| 110 */ | |
| 111 List<E> toList(); | 81 List<E> toList(); |
| 112 | 82 |
| 113 /** | 83 /// Return a comparator based set using the comparator of this queue. |
| 114 * Return a comparator based set using the comparator of this queue. | 84 /// |
| 115 * | 85 /// The queue is not modified. |
| 116 * The queue is not modified. | 86 /// |
| 117 * | 87 /// The returned [Set] is currently a [SplayTreeSet], |
| 118 * The returned [Set] is currently a [SplayTreeSet], | 88 /// but this may change as other ordered sets are implemented. |
| 119 * but this may change as other ordered sets are implemented. | 89 /// |
| 120 * | 90 /// The set contains all the elements of this queue. |
| 121 * The set contains all the elements of this queue. | 91 /// If an element occurs more than once in the queue, |
| 122 * If an element occurs more than once in the queue, | 92 /// the set will contain it only once. |
| 123 * the set will contain it only once. | |
| 124 */ | |
| 125 Set<E> toSet(); | 93 Set<E> toSet(); |
| 126 } | 94 } |
| 127 | 95 |
| 128 /** | 96 /// Heap based priority queue. |
| 129 * Heap based priority queue. | 97 /// |
| 130 * | 98 /// The elements are kept in a heap structure, |
| 131 * The elements are kept in a heap structure, | 99 /// where the element with the highest priority is immediately accessible, |
| 132 * where the element with the highest priority is immediately accessible, | 100 /// and modifying a single element takes |
| 133 * and modifying a single element takes | 101 /// logarithmic time in the number of elements on average. |
| 134 * logarithmic time in the number of elements on average. | 102 /// |
| 135 * | 103 /// * The [add] and [removeFirst] operations take amortized logarithmic time, |
| 136 * * The [add] and [removeFirst] operations take amortized logarithmic time, | 104 /// O(log(n)), but may occasionally take linear time when growing the capacity |
| 137 * O(log(n)), but may occasionally take linear time when growing the capacity | 105 /// of the heap. |
| 138 * of the heap. | 106 /// * The [addAll] operation works as doing repeated [add] operations. |
| 139 * * The [addAll] operation works as doing repeated [add] operations. | 107 /// * The [first] getter takes constant time, O(1). |
| 140 * * The [first] getter takes constant time, O(1). | 108 /// * The [clear] and [removeAll] methods also take constant time, O(1). |
| 141 * * The [clear] and [removeAll] methods also take constant time, O(1). | 109 /// * The [contains] and [remove] operations may need to search the entire |
| 142 * * The [contains] and [remove] operations may need to search the entire | 110 /// queue for the elements, taking O(n) time. |
| 143 * queue for the elements, taking O(n) time. | 111 /// * The [toList] operation effectively sorts the elements, taking O(n*log(n)) |
| 144 * * The [toList] operation effectively sorts the elements, taking O(n*log(n)) | 112 /// time. |
| 145 * time. | 113 /// * The [toSet] operation effectively adds each element to the new set, taking |
| 146 * * The [toSet] operation effectively adds each element to the new set, taking | 114 /// an expected O(n*log(n)) time. |
| 147 * an expected O(n*log(n)) time. | |
| 148 */ | |
| 149 class HeapPriorityQueue<E> implements PriorityQueue<E> { | 115 class HeapPriorityQueue<E> implements PriorityQueue<E> { |
| 150 /** | 116 /// Initial capacity of a queue when created, or when added to after a |
| 151 * Initial capacity of a queue when created, or when added to after a [clear]. | 117 /// [clear]. |
| 152 * | 118 /// |
| 153 * Number can be any positive value. Picking a size that gives a whole | 119 /// Number can be any positive value. Picking a size that gives a whole |
| 154 * number of "tree levels" in the heap is only done for aesthetic reasons. | 120 /// number of "tree levels" in the heap is only done for aesthetic reasons. |
| 155 */ | |
| 156 static const int _INITIAL_CAPACITY = 7; | 121 static const int _INITIAL_CAPACITY = 7; |
| 157 | 122 |
| 158 /** | 123 /// The comparison being used to compare the priority of elements. |
| 159 * The comparison being used to compare the priority of elements. | |
| 160 */ | |
| 161 final Comparator comparison; | 124 final Comparator comparison; |
| 162 | 125 |
| 163 /** | 126 /// List implementation of a heap. |
| 164 * List implementation of a heap. | |
| 165 */ | |
| 166 List<E> _queue = new List<E>(_INITIAL_CAPACITY); | 127 List<E> _queue = new List<E>(_INITIAL_CAPACITY); |
| 167 | 128 |
| 168 /** | 129 /// Number of elements in queue. |
| 169 * Number of elements in queue. | 130 /// |
| 170 * | 131 /// The heap is implemented in the first [_length] entries of [_queue]. |
| 171 * The heap is implemented in the first [_length] entries of [_queue]. | |
| 172 */ | |
| 173 int _length = 0; | 132 int _length = 0; |
| 174 | 133 |
| 175 /** | 134 /// Create a new priority queue. |
| 176 * Create a new priority queue. | 135 /// |
| 177 * | 136 /// The [comparison] is a [Comparator] used to compare the priority of |
| 178 * The [comparison] is a [Comparator] used to compare the priority of | 137 /// elements. An element that compares as less than another element has |
| 179 * elements. An element that compares as less than another element has | 138 /// a higher priority. |
| 180 * a higher priority. | 139 /// |
| 181 * | 140 /// If [comparison] is omitted, it defaults to [Comparable.compare]. |
| 182 * If [comparison] is omitted, it defaults to [Comparable.compare]. | |
| 183 */ | |
| 184 HeapPriorityQueue([int comparison(E e1, E e2)]) | 141 HeapPriorityQueue([int comparison(E e1, E e2)]) |
| 185 : comparison = (comparison != null) ? comparison : Comparable.compare; | 142 : comparison = (comparison != null) ? comparison : Comparable.compare; |
| 186 | 143 |
| 187 void add(E element) { | 144 void add(E element) { |
| 188 _add(element); | 145 _add(element); |
| 189 } | 146 } |
| 190 | 147 |
| 191 void addAll(Iterable<E> elements) { | 148 void addAll(Iterable<E> elements) { |
| 192 for (E element in elements) { | 149 for (E element in elements) { |
| 193 _add(element); | 150 _add(element); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 255 } | 212 } |
| 256 | 213 |
| 257 Set<E> toSet() { | 214 Set<E> toSet() { |
| 258 Set<E> set = new SplayTreeSet<E>(comparison); | 215 Set<E> set = new SplayTreeSet<E>(comparison); |
| 259 for (int i = 0; i < _length; i++) { | 216 for (int i = 0; i < _length; i++) { |
| 260 set.add(_queue[i]); | 217 set.add(_queue[i]); |
| 261 } | 218 } |
| 262 return set; | 219 return set; |
| 263 } | 220 } |
| 264 | 221 |
| 265 /** | 222 /// Returns some representation of the queue. |
| 266 * Returns some representation of the queue. | 223 /// |
| 267 * | 224 /// The format isn't significant, and may change in the future. |
| 268 * The format isn't significant, and may change in the future. | |
| 269 */ | |
| 270 String toString() { | 225 String toString() { |
| 271 return _queue.take(_length).toString(); | 226 return _queue.take(_length).toString(); |
| 272 } | 227 } |
| 273 | 228 |
| 274 /** | 229 /// Add element to the queue. |
| 275 * Add element to the queue. | 230 /// |
| 276 * | 231 /// Grows the capacity if the backing list is full. |
| 277 * Grows the capacity if the backing list is full. | |
| 278 */ | |
| 279 void _add(E element) { | 232 void _add(E element) { |
| 280 if (_length == _queue.length) _grow(); | 233 if (_length == _queue.length) _grow(); |
| 281 _bubbleUp(element, _length++); | 234 _bubbleUp(element, _length++); |
| 282 } | 235 } |
| 283 | 236 |
| 284 /** | 237 /// Find the index of an object in the heap. |
| 285 * Find the index of an object in the heap. | 238 /// |
| 286 * | 239 /// Returns -1 if the object is not found. |
| 287 * Returns -1 if the object is not found. | |
| 288 */ | |
| 289 int _locate(E object) { | 240 int _locate(E object) { |
| 290 if (_length == 0) return -1; | 241 if (_length == 0) return -1; |
| 291 // Count positions from one instead of zero. This gives the numbers | 242 // Count positions from one instead of zero. This gives the numbers |
| 292 // some nice properties. For example, all right children are odd, | 243 // some nice properties. For example, all right children are odd, |
| 293 // their left sibling is even, and the parent is found by shifting | 244 // their left sibling is even, and the parent is found by shifting |
| 294 // right by one. | 245 // right by one. |
| 295 // Valid range for position is [1.._length], inclusive. | 246 // Valid range for position is [1.._length], inclusive. |
| 296 int position = 1; | 247 int position = 1; |
| 297 // Pre-order depth first search, omit child nodes if the current | 248 // Pre-order depth first search, omit child nodes if the current |
| 298 // node has lower priority than [object], because all nodes lower | 249 // node has lower priority than [object], because all nodes lower |
| (...skipping 26 matching lines...) Expand all Loading... |
| 325 } | 276 } |
| 326 | 277 |
| 327 E _removeLast() { | 278 E _removeLast() { |
| 328 int newLength = _length - 1; | 279 int newLength = _length - 1; |
| 329 E last = _queue[newLength]; | 280 E last = _queue[newLength]; |
| 330 _queue[newLength] = null; | 281 _queue[newLength] = null; |
| 331 _length = newLength; | 282 _length = newLength; |
| 332 return last; | 283 return last; |
| 333 } | 284 } |
| 334 | 285 |
| 335 /** | 286 /// Place [element] in heap at [index] or above. |
| 336 * Place [element] in heap at [index] or above. | 287 /// |
| 337 * | 288 /// Put element into the empty cell at `index`. |
| 338 * Put element into the empty cell at `index`. | 289 /// While the `element` has higher priority than the |
| 339 * While the `element` has higher priority than the | 290 /// parent, swap it with the parent. |
| 340 * parent, swap it with the parent. | |
| 341 */ | |
| 342 void _bubbleUp(E element, int index) { | 291 void _bubbleUp(E element, int index) { |
| 343 while (index > 0) { | 292 while (index > 0) { |
| 344 int parentIndex = (index - 1) ~/ 2; | 293 int parentIndex = (index - 1) ~/ 2; |
| 345 E parent = _queue[parentIndex]; | 294 E parent = _queue[parentIndex]; |
| 346 if (comparison(element, parent) > 0) break; | 295 if (comparison(element, parent) > 0) break; |
| 347 _queue[index] = parent; | 296 _queue[index] = parent; |
| 348 index = parentIndex; | 297 index = parentIndex; |
| 349 } | 298 } |
| 350 _queue[index] = element; | 299 _queue[index] = element; |
| 351 } | 300 } |
| 352 | 301 |
| 353 /** | 302 /// Place [element] in heap at [index] or above. |
| 354 * Place [element] in heap at [index] or above. | 303 /// |
| 355 * | 304 /// Put element into the empty cell at `index`. |
| 356 * Put element into the empty cell at `index`. | 305 /// While the `element` has lower priority than either child, |
| 357 * While the `element` has lower priority than either child, | 306 /// swap it with the highest priority child. |
| 358 * swap it with the highest priority child. | |
| 359 */ | |
| 360 void _bubbleDown(E element, int index) { | 307 void _bubbleDown(E element, int index) { |
| 361 int rightChildIndex = index * 2 + 2; | 308 int rightChildIndex = index * 2 + 2; |
| 362 while (rightChildIndex < _length) { | 309 while (rightChildIndex < _length) { |
| 363 int leftChildIndex = rightChildIndex - 1; | 310 int leftChildIndex = rightChildIndex - 1; |
| 364 E leftChild = _queue[leftChildIndex]; | 311 E leftChild = _queue[leftChildIndex]; |
| 365 E rightChild = _queue[rightChildIndex]; | 312 E rightChild = _queue[rightChildIndex]; |
| 366 int comp = comparison(leftChild, rightChild); | 313 int comp = comparison(leftChild, rightChild); |
| 367 int minChildIndex; | 314 int minChildIndex; |
| 368 E minChild; | 315 E minChild; |
| 369 if (comp < 0) { | 316 if (comp < 0) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 387 E child = _queue[leftChildIndex]; | 334 E child = _queue[leftChildIndex]; |
| 388 int comp = comparison(element, child); | 335 int comp = comparison(element, child); |
| 389 if (comp > 0) { | 336 if (comp > 0) { |
| 390 _queue[index] = child; | 337 _queue[index] = child; |
| 391 index = leftChildIndex; | 338 index = leftChildIndex; |
| 392 } | 339 } |
| 393 } | 340 } |
| 394 _queue[index] = element; | 341 _queue[index] = element; |
| 395 } | 342 } |
| 396 | 343 |
| 397 /** | 344 /// Grows the capacity of the list holding the heap. |
| 398 * Grows the capacity of the list holding the heap. | 345 /// |
| 399 * | 346 /// Called when the list is full. |
| 400 * Called when the list is full. | |
| 401 */ | |
| 402 void _grow() { | 347 void _grow() { |
| 403 int newCapacity = _queue.length * 2 + 1; | 348 int newCapacity = _queue.length * 2 + 1; |
| 404 if (newCapacity < _INITIAL_CAPACITY) newCapacity = _INITIAL_CAPACITY; | 349 if (newCapacity < _INITIAL_CAPACITY) newCapacity = _INITIAL_CAPACITY; |
| 405 List<E> newQueue = new List<E>(newCapacity); | 350 List<E> newQueue = new List<E>(newCapacity); |
| 406 newQueue.setRange(0, _length, _queue); | 351 newQueue.setRange(0, _length, _queue); |
| 407 _queue = newQueue; | 352 _queue = newQueue; |
| 408 } | 353 } |
| 409 } | 354 } |
| OLD | NEW |