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

Side by Side Diff: packages/collection/lib/algorithms.dart

Issue 2989763002: Update charted to 0.4.8 and roll (Closed)
Patch Set: Removed Cutch from list of reviewers Created 3 years, 4 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 | « packages/collection/README.md ('k') | packages/collection/lib/collection.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) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 /** 5 /// Import `collection.dart` instead.
6 * Operations on collections. 6 @Deprecated("Will be removed in collection 2.0.0.")
7 */
8 library dart.pkg.collection.algorithms; 7 library dart.pkg.collection.algorithms;
9 8
10 import "dart:math" show Random; 9 export "src/algorithms.dart";
11
12 /** Version of [binarySearch] optimized for comparable keys */
13 int _comparableBinarySearch(List<Comparable> list, Comparable key) {
14 int min = 0;
15 int max = list.length;
16 while (min < max) {
17 int mid = min + ((max - min) >> 1);
18 var element = list[mid];
19 int comp = element.compareTo(key);
20 if (comp == 0) return mid;
21 if (comp < 0) {
22 min = mid + 1;
23 } else {
24 max = mid;
25 }
26 }
27 return -1;
28 }
29
30 /**
31 * Returns a position of the [key] in [sortedList], if it is there.
32 *
33 * If the list isn't sorted according to the [compare] function, the result
34 * is unpredictable.
35 *
36 * If [compare] is omitted, it defaults to calling [Comparable.compareTo] on
37 * the objects.
38 *
39 * Returns -1 if [key] is not in the list by default.
40 */
41 int binarySearch(List sortedList, var key,
42 { int compare(var a, var b) }) {
43 if (compare == null) {
44 return _comparableBinarySearch(sortedList, key);
45 }
46 int min = 0;
47 int max = sortedList.length;
48 while (min < max) {
49 int mid = min + ((max - min) >> 1);
50 var element = sortedList[mid];
51 int comp = compare(element, key);
52 if (comp == 0) return mid;
53 if (comp < 0) {
54 min = mid + 1;
55 } else {
56 max = mid;
57 }
58 }
59 return -1;
60 }
61
62
63 /**
64 * Shuffles a list randomly.
65 *
66 * A sub-range of a list can be shuffled by providing [start] and [end].
67 */
68 void shuffle(List list, [int start = 0, int end = null]) {
69 Random random = new Random();
70 if (end == null) end = list.length;
71 int length = end - start;
72 while (length > 1) {
73 int pos = random.nextInt(length);
74 length--;
75 var tmp1 = list[start + pos];
76 list[start + pos] = list[start + length];
77 list[start + length] = tmp1;
78 }
79 }
80
81
82 /**
83 * Reverses a list, or a part of a list, in-place.
84 */
85 void reverse(List list, [int start = 0, int end = null]) {
86 if (end == null) end = list.length;
87 _reverse(list, start, end);
88 }
89
90 // Internal helper function that assumes valid arguments.
91 void _reverse(List list, int start, int end) {
92 for (int i = start, j = end - 1; i < j; i++, j--) {
93 var tmp = list[i];
94 list[i] = list[j];
95 list[j] = tmp;
96 }
97 }
98
99 /**
100 * Sort a list using insertion sort.
101 *
102 * Insertion sort is a simple sorting algorithm. For `n` elements it does on
103 * the order of `n * log(n)` comparisons but up to `n` squared moves. The
104 * sorting is performed in-place, without using extra memory.
105 *
106 * For short lists the many moves have less impact than the simple algorithm,
107 * and it is often the favored sorting algorithm for short lists.
108 *
109 * This insertion sort is stable: Equal elements end up in the same order
110 * as they started in.
111 */
112 void insertionSort(List list,
113 { int compare(a, b),
114 int start: 0,
115 int end: null }) {
116 // If the same method could have both positional and named optional
117 // parameters, this should be (list, [start, end], {compare}).
118 if (end == null) end = list.length;
119 if (compare == null) compare = Comparable.compare;
120 _insertionSort(list, compare, start, end, start + 1);
121 }
122
123 /**
124 * Internal helper function that assumes arguments correct.
125 *
126 * Assumes that the elements up to [sortedUntil] (not inclusive) are
127 * already sorted. The [sortedUntil] values should always be at least
128 * `start + 1`.
129 */
130 void _insertionSort(List list, int compare(a, b), int start, int end,
131 int sortedUntil) {
132 for (int pos = sortedUntil; pos < end; pos++) {
133 int min = start;
134 int max = pos;
135 var element = list[pos];
136 while (min < max) {
137 int mid = min + ((max - min) >> 1);
138 int comparison = compare(element, list[mid]);
139 if (comparison < 0) {
140 max = mid;
141 } else {
142 min = mid + 1;
143 }
144 }
145 list.setRange(min + 1, pos + 1, list, min);
146 list[min] = element;
147 }
148 }
149
150 /** Limit below which merge sort defaults to insertion sort. */
151 const int _MERGE_SORT_LIMIT = 32;
152
153 /**
154 * Sorts a list, or a range of a list, using the merge sort algorithm.
155 *
156 * Merge-sorting works by splitting the job into two parts, sorting each
157 * recursively, and then merging the two sorted parts.
158 *
159 * This takes on the order of `n * log(n)` comparisons and moves to sort
160 * `n` elements, but requires extra space of about the same size as the list
161 * being sorted.
162 *
163 * This merge sort is stable: Equal elements end up in the same order
164 * as they started in.
165 */
166 void mergeSort(List list, {int start: 0, int end: null, int compare(a, b)}) {
167 if (end == null) end = list.length;
168 if (compare == null) compare = Comparable.compare;
169 int length = end - start;
170 if (length < 2) return;
171 if (length < _MERGE_SORT_LIMIT) {
172 _insertionSort(list, compare, start, end, start + 1);
173 return;
174 }
175 // Special case the first split instead of directly calling
176 // _mergeSort, because the _mergeSort requires its target to
177 // be different from its source, and it requires extra space
178 // of the same size as the list to sort.
179 // This split allows us to have only half as much extra space,
180 // and it ends up in the original place.
181 int middle = start + ((end - start) >> 1);
182 int firstLength = middle - start;
183 int secondLength = end - middle;
184 // secondLength is always the same as firstLength, or one greater.
185 List scratchSpace = new List(secondLength);
186 _mergeSort(list, compare, middle, end, scratchSpace, 0);
187 int firstTarget = end - firstLength;
188 _mergeSort(list, compare, start, middle, list, firstTarget);
189 _merge(compare,
190 list, firstTarget, end,
191 scratchSpace, 0, secondLength,
192 list, start);
193 }
194
195 /**
196 * Performs an insertion sort into a potentially different list than the
197 * one containing the original values.
198 *
199 * It will work in-place as well.
200 */
201 void _movingInsertionSort(List list, int compare(a, b), int start, int end,
202 List target, int targetOffset) {
203 int length = end - start;
204 if (length == 0) return;
205 target[targetOffset] = list[start];
206 for (int i = 1; i < length; i++) {
207 var element = list[start + i];
208 int min = targetOffset;
209 int max = targetOffset + i;
210 while (min < max) {
211 int mid = min + ((max - min) >> 1);
212 if (compare(element, target[mid]) < 0) {
213 max = mid;
214 } else {
215 min = mid + 1;
216 }
217 }
218 target.setRange(min + 1, targetOffset + i + 1,
219 target, min);
220 target[min] = element;
221 }
222 }
223
224 /**
225 * Sorts [list] from [start] to [end] into [target] at [targetOffset].
226 *
227 * The `target` list must be able to contain the range from `start` to `end`
228 * after `targetOffset`.
229 *
230 * Allows target to be the same list as [list], as long as it's not
231 * overlapping the `start..end` range.
232 */
233 void _mergeSort(List list, int compare(a, b), int start, int end,
234 List target, int targetOffset) {
235 int length = end - start;
236 if (length < _MERGE_SORT_LIMIT) {
237 _movingInsertionSort(list, compare, start, end, target, targetOffset);
238 return;
239 }
240 int middle = start + (length >> 1);
241 int firstLength = middle - start;
242 int secondLength = end - middle;
243 // Here secondLength >= firstLength (differs by at most one).
244 int targetMiddle = targetOffset + firstLength;
245 // Sort the second half into the end of the target area.
246 _mergeSort(list, compare, middle, end,
247 target, targetMiddle);
248 // Sort the first half into the end of the source area.
249 _mergeSort(list, compare, start, middle,
250 list, middle);
251 // Merge the two parts into the target area.
252 _merge(compare,
253 list, middle, middle + firstLength,
254 target, targetMiddle, targetMiddle + secondLength,
255 target, targetOffset);
256 }
257
258 /**
259 * Merges two lists into a target list.
260 *
261 * One of the input lists may be positioned at the end of the target
262 * list.
263 *
264 * For equal object, elements from [firstList] are always preferred.
265 * This allows the merge to be stable if the first list contains elements
266 * that started out earlier than the ones in [secondList]
267 */
268 void _merge(int compare(a, b),
269 List firstList, int firstStart, int firstEnd,
270 List secondList, int secondStart, int secondEnd,
271 List target, int targetOffset) {
272 // No empty lists reaches here.
273 assert(firstStart < firstEnd);
274 assert(secondStart < secondEnd);
275 int cursor1 = firstStart;
276 int cursor2 = secondStart;
277 var firstElement = firstList[cursor1++];
278 var secondElement = secondList[cursor2++];
279 while (true) {
280 if (compare(firstElement, secondElement) <= 0) {
281 target[targetOffset++] = firstElement;
282 if (cursor1 == firstEnd) break; // Flushing second list after loop.
283 firstElement = firstList[cursor1++];
284 } else {
285 target[targetOffset++] = secondElement;
286 if (cursor2 != secondEnd) {
287 secondElement = secondList[cursor2++];
288 continue;
289 }
290 // Second list empties first. Flushing first list here.
291 target[targetOffset++] = firstElement;
292 target.setRange(targetOffset, targetOffset + (firstEnd - cursor1),
293 firstList, cursor1);
294 return;
295 }
296 }
297 // First list empties first. Reached by break above.
298 target[targetOffset++] = secondElement;
299 target.setRange(targetOffset, targetOffset + (secondEnd - cursor2),
300 secondList, cursor2);
301 }
OLDNEW
« no previous file with comments | « packages/collection/README.md ('k') | packages/collection/lib/collection.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698