| 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 // TODO(ahe): Remove this file and use the shared one. |
| 6 |
| 5 /** | 7 /** |
| 6 * Dual-Pivot Quicksort algorithm. | 8 * Dual-Pivot Quicksort algorithm. |
| 7 * | 9 * |
| 8 * This class implements the dual-pivot quicksort algorithm as presented in | 10 * This class implements the dual-pivot quicksort algorithm as presented in |
| 9 * Vladimir Yaroslavskiy's paper. | 11 * Vladimir Yaroslavskiy's paper. |
| 10 * | 12 * |
| 11 * Some improvements have been copied from Android's implementation. | 13 * Some improvements have been copied from Android's implementation. |
| 12 */ | 14 */ |
| 13 class DualPivotQuicksort { | 15 class DualPivotQuicksort { |
| 14 // When a list has less then [:_INSERTION_SORT_THRESHOLD:] elements it will | 16 // When a list has less then [:_INSERTION_SORT_THRESHOLD:] elements it will |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 128 // a[left] and a[right] are undefined and are filled after the | 130 // a[left] and a[right] are undefined and are filled after the |
| 129 // partitioning. | 131 // partitioning. |
| 130 // | 132 // |
| 131 // Invariants: | 133 // Invariants: |
| 132 // 1) for x in ]left, less[ : x < pivot. | 134 // 1) for x in ]left, less[ : x < pivot. |
| 133 // 2) for x in [less, k[ : x == pivot. | 135 // 2) for x in [less, k[ : x == pivot. |
| 134 // 3) for x in ]great, right[ : x > pivot. | 136 // 3) for x in ]great, right[ : x > pivot. |
| 135 for (int k = less; k <= great; k++) { | 137 for (int k = less; k <= great; k++) { |
| 136 var ak = a[k]; | 138 var ak = a[k]; |
| 137 int comp = compare(ak, pivot); | 139 int comp = compare(ak, pivot); |
| 138 if (comp == 0) continue; | 140 if (comp == 0) { |
| 139 if (comp < 0) { | 141 } else if (comp < 0) { |
| 140 if (k != less) { | 142 if (k != less) { |
| 141 a[k] = a[less]; | 143 a[k] = a[less]; |
| 142 a[less] = ak; | 144 a[less] = ak; |
| 143 } | 145 } |
| 144 less++; | 146 less++; |
| 145 } else { | 147 } else { |
| 146 // comp > 0. | 148 // comp > 0. |
| 147 // | 149 // |
| 148 // Find the first element <= pivot in the range [k - 1, great] and | 150 // Find the first element <= pivot in the range [k - 1, great] and |
| 149 // put [:ak:] there. We know that such an element must exist: | 151 // put [:ak:] there. We know that such an element must exist: |
| 150 // When k == less, then el3 (which is equal to pivot) lies in the | 152 // When k == less, then el3 (which is equal to pivot) lies in the |
| 151 // interval. Otherwise a[k - 1] == pivot and the search stops at k-1. | 153 // interval. Otherwise a[k - 1] == pivot and the search stops at k-1. |
| 152 // Note that in the latter case invariant 2 will be violated for a | 154 // Note that in the latter case invariant 2 will be violated for a |
| 153 // short amount of time. The invariant will be restored when the | 155 // short amount of time. The invariant will be restored when the |
| 154 // pivots are put into their final positions. | 156 // pivots are put into their final positions. |
| 155 while (true) { | 157 while (true) { |
| 156 comp = compare(a[great], pivot); | 158 comp = compare(a[great], pivot); |
| 157 if (comp > 0) { | 159 if (comp > 0) { |
| 158 great--; | 160 great--; |
| 159 // This is the only location in the while-loop where a new | 161 // This is the only location in the while-loop where a new |
| 160 // iteration is started. | 162 // iteration is started. |
| 161 continue; | 163 // continue; |
| 162 } else if (comp < 0) { | 164 } else if (comp < 0) { |
| 163 // Triple exchange. | 165 // Triple exchange. |
| 164 a[k] = a[less]; | 166 a[k] = a[less]; |
| 165 a[less++] = a[great]; | 167 a[less++] = a[great]; |
| 166 a[great--] = ak; | 168 a[great--] = ak; |
| 167 break; | 169 break; |
| 168 } else { | 170 } else { |
| 169 // comp == 0; | 171 // comp == 0; |
| 170 a[k] = a[great]; | 172 a[k] = a[great]; |
| 171 a[great--] = ak; | 173 a[great--] = ak; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 206 } else { | 208 } else { |
| 207 int comp_pivot2 = compare(ak, pivot2); | 209 int comp_pivot2 = compare(ak, pivot2); |
| 208 if (comp_pivot2 > 0) { | 210 if (comp_pivot2 > 0) { |
| 209 while (true) { | 211 while (true) { |
| 210 int comp = compare(a[great], pivot2); | 212 int comp = compare(a[great], pivot2); |
| 211 if (comp > 0) { | 213 if (comp > 0) { |
| 212 great--; | 214 great--; |
| 213 if (great < k) break; | 215 if (great < k) break; |
| 214 // This is the only location inside the loop where a new | 216 // This is the only location inside the loop where a new |
| 215 // iteration is started. | 217 // iteration is started. |
| 216 continue; | 218 // continue; |
| 217 } else { | 219 } else { |
| 218 // a[great] <= pivot2. | 220 // a[great] <= pivot2. |
| 219 comp = compare(a[great], pivot1); | 221 comp = compare(a[great], pivot1); |
| 220 if (comp < 0) { | 222 if (comp < 0) { |
| 221 // Triple exchange. | 223 // Triple exchange. |
| 222 a[k] = a[less]; | 224 a[k] = a[less]; |
| 223 a[less++] = a[great]; | 225 a[less++] = a[great]; |
| 224 a[great--] = ak; | 226 a[great--] = ak; |
| 225 } else { | 227 } else { |
| 226 // a[great] >= pivot1. | 228 // a[great] >= pivot1. |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 296 } else { | 298 } else { |
| 297 int comp_pivot2 = compare(ak, pivot2); | 299 int comp_pivot2 = compare(ak, pivot2); |
| 298 if (comp_pivot2 == 0) { | 300 if (comp_pivot2 == 0) { |
| 299 while (true) { | 301 while (true) { |
| 300 int comp = compare(a[great], pivot2); | 302 int comp = compare(a[great], pivot2); |
| 301 if (comp == 0) { | 303 if (comp == 0) { |
| 302 great--; | 304 great--; |
| 303 if (great < k) break; | 305 if (great < k) break; |
| 304 // This is the only location inside the loop where a new | 306 // This is the only location inside the loop where a new |
| 305 // iteration is started. | 307 // iteration is started. |
| 306 continue; | 308 // continue; |
| 307 } else { | 309 } else { |
| 308 // a[great] < pivot2. | 310 // a[great] < pivot2. |
| 309 comp = compare(a[great], pivot1); | 311 comp = compare(a[great], pivot1); |
| 310 if (comp < 0) { | 312 if (comp < 0) { |
| 311 // Triple exchange. | 313 // Triple exchange. |
| 312 a[k] = a[less]; | 314 a[k] = a[less]; |
| 313 a[less++] = a[great]; | 315 a[less++] = a[great]; |
| 314 a[great--] = ak; | 316 a[great--] = ak; |
| 315 } else { | 317 } else { |
| 316 // a[great] == pivot1. | 318 // a[great] == pivot1. |
| (...skipping 16 matching lines...) Expand all Loading... |
| 333 } else { | 335 } else { |
| 334 // The second partition looks as follows: | 336 // The second partition looks as follows: |
| 335 // [ * | >= pivot1 && <= pivot2 | * ] | 337 // [ * | >= pivot1 && <= pivot2 | * ] |
| 336 // ^ ^ | 338 // ^ ^ |
| 337 // less great | 339 // less great |
| 338 // Simply sort it by recursive descent. | 340 // Simply sort it by recursive descent. |
| 339 _doSort(a, less, great, compare); | 341 _doSort(a, less, great, compare); |
| 340 } | 342 } |
| 341 } | 343 } |
| 342 } | 344 } |
| OLD | NEW |