Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(509)

Side by Side Diff: lib/priority_queue.dart

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

Powered by Google App Engine
This is Rietveld 408576698