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