LCOV - code coverage report
Current view: top level - collection-1.14.3/lib/src - priority_queue.dart (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 0 86 0.0 %
Date: 2017-10-10 20:17:03 Functions: 0 0 -

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

Generated by: LCOV version 1.13