OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 part of dart._internal; | 5 part of dart._internal; |
6 | 6 |
7 /** | 7 /** |
8 * Dual-Pivot Quicksort algorithm. | 8 * Dual-Pivot Quicksort algorithm. |
9 * | 9 * |
10 * This class implements the dual-pivot quicksort algorithm as presented in | 10 * This class implements the dual-pivot quicksort algorithm as presented in |
(...skipping 11 matching lines...) Expand all Loading... |
22 * [:compare:] function. | 22 * [:compare:] function. |
23 * | 23 * |
24 * The [:compare:] function takes two arguments [:x:] and [:y:] and returns | 24 * The [:compare:] function takes two arguments [:x:] and [:y:] and returns |
25 * -1 if [:x < y:], | 25 * -1 if [:x < y:], |
26 * 0 if [:x == y:], and | 26 * 0 if [:x == y:], and |
27 * 1 if [:x > y:]. | 27 * 1 if [:x > y:]. |
28 * | 28 * |
29 * The function's behavior must be consistent. It must not return different | 29 * The function's behavior must be consistent. It must not return different |
30 * results for the same values. | 30 * results for the same values. |
31 */ | 31 */ |
32 static void sort/*<E>*/(List/*<E>*/ a, int compare(dynamic /*=E*/ a, dynamic /
*=E*/ b)) { | 32 static void sort<E>(List<E> a, int compare(E a, E b)) { |
33 _doSort(a, 0, a.length - 1, compare); | 33 _doSort(a, 0, a.length - 1, compare); |
34 } | 34 } |
35 | 35 |
36 /** | 36 /** |
37 * Sorts all elements in the range [:from:] (inclusive) to [:to:] (exclusive) | 37 * Sorts all elements in the range [:from:] (inclusive) to [:to:] (exclusive) |
38 * of the given list [:a:]. | 38 * of the given list [:a:]. |
39 * | 39 * |
40 * If the given range is invalid an "OutOfRange" error is raised. | 40 * If the given range is invalid an "OutOfRange" error is raised. |
41 * TODO(floitsch): do we want an error? | 41 * TODO(floitsch): do we want an error? |
42 * | 42 * |
43 * See [:sort:] for requirements of the [:compare:] function. | 43 * See [:sort:] for requirements of the [:compare:] function. |
44 */ | 44 */ |
45 static void sortRange/*<E>*/(List/*<E>*/ a, int from, int to, int compare(dyna
mic /*=E*/ a, dynamic /*=E*/ b)) { | 45 static void sortRange<E>(List<E> a, int from, int to, int compare(E a, E b)) { |
46 if ((from < 0) || (to > a.length) || (to < from)) { | 46 if ((from < 0) || (to > a.length) || (to < from)) { |
47 throw "OutOfRange"; | 47 throw "OutOfRange"; |
48 } | 48 } |
49 _doSort(a, from, to - 1, compare); | 49 _doSort(a, from, to - 1, compare); |
50 } | 50 } |
51 | 51 |
52 /** | 52 /** |
53 * Sorts the list in the interval [:left:] to [:right:] (both inclusive). | 53 * Sorts the list in the interval [:left:] to [:right:] (both inclusive). |
54 */ | 54 */ |
55 static void _doSort/*<E>*/(List/*<E>*/ a, int left, int right, int compare(dyn
amic /*=E*/ a, dynamic /*=E*/ b)) { | 55 static void _doSort<E>(List<E> a, int left, int right, |
| 56 int compare(E a, E b)) { |
56 if ((right - left) <= _INSERTION_SORT_THRESHOLD) { | 57 if ((right - left) <= _INSERTION_SORT_THRESHOLD) { |
57 _insertionSort(a, left, right, compare); | 58 _insertionSort(a, left, right, compare); |
58 } else { | 59 } else { |
59 _dualPivotQuicksort(a, left, right, compare); | 60 _dualPivotQuicksort(a, left, right, compare); |
60 } | 61 } |
61 } | 62 } |
62 | 63 |
63 static void _insertionSort/*<E>*/(List/*<E>*/ a, int left, int right, int comp
are(dynamic /*=E*/ a, dynamic /*=E*/ b)) { | 64 static void _insertionSort<E>(List<E> a, int left, int right, |
| 65 int compare(E a, E b)) { |
64 for (int i = left + 1; i <= right; i++) { | 66 for (int i = left + 1; i <= right; i++) { |
65 var el = a[i]; | 67 var el = a[i]; |
66 int j = i; | 68 int j = i; |
67 while ((j > left) && (compare(a[j - 1], el) > 0)) { | 69 while ((j > left) && (compare(a[j - 1], el) > 0)) { |
68 a[j] = a[j - 1]; | 70 a[j] = a[j - 1]; |
69 j--; | 71 j--; |
70 } | 72 } |
71 a[j] = el; | 73 a[j] = el; |
72 } | 74 } |
73 } | 75 } |
74 | 76 |
75 static void _dualPivotQuicksort/*<E>*/(List/*<E>*/ a, | 77 static void _dualPivotQuicksort<E>(List<E> a, int left, int right, |
76 int left, int right, | 78 int compare(E a, E b)) { |
77 int compare(dynamic /*=E*/ a, dynamic /*=E*/ b
)) { | |
78 assert(right - left > _INSERTION_SORT_THRESHOLD); | 79 assert(right - left > _INSERTION_SORT_THRESHOLD); |
79 | 80 |
80 // Compute the two pivots by looking at 5 elements. | 81 // Compute the two pivots by looking at 5 elements. |
81 int sixth = (right - left + 1) ~/ 6; | 82 int sixth = (right - left + 1) ~/ 6; |
82 int index1 = left + sixth; | 83 int index1 = left + sixth; |
83 int index5 = right - sixth; | 84 int index5 = right - sixth; |
84 int index3 = (left + right) ~/ 2; // The midpoint. | 85 int index3 = (left + right) ~/ 2; // The midpoint. |
85 int index2 = index3 - sixth; | 86 int index2 = index3 - sixth; |
86 int index4 = index3 + sixth; | 87 int index4 = index3 + sixth; |
87 | 88 |
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
335 } else { | 336 } else { |
336 // The second partition looks as follows: | 337 // The second partition looks as follows: |
337 // [ * | >= pivot1 && <= pivot2 | * ] | 338 // [ * | >= pivot1 && <= pivot2 | * ] |
338 // ^ ^ | 339 // ^ ^ |
339 // less great | 340 // less great |
340 // Simply sort it by recursive descent. | 341 // Simply sort it by recursive descent. |
341 _doSort(a, less, great, compare); | 342 _doSort(a, less, great, compare); |
342 } | 343 } |
343 } | 344 } |
344 } | 345 } |
OLD | NEW |