1use std::{cmp::Ordering, ops::Range};
36
37pub trait Sortable {
39 fn swap(&mut self, i: usize, j: usize);
41
42 fn compare(&self, i: usize, j: usize) -> Ordering;
44}
45
46impl<T: Ord> Sortable for [T] {
48 fn swap(&mut self, i: usize, j: usize) {
49 (*self).swap(i, j);
50 }
51
52 fn compare(&self, i: usize, j: usize) -> Ordering {
53 self[i].cmp(&self[j])
54 }
55}
56
57impl <T: Ord> Sortable for Vec<T> {
59 fn swap(&mut self, i: usize, j: usize) {
60 self[..].swap(i, j)
61 }
62 fn compare(&self, i: usize, j: usize) -> Ordering {
63 self[i].cmp(&self[j])
64 }
65}
66
67impl<S: Sortable, T: Sortable> Sortable for (S, T) {
69 fn swap(&mut self, i: usize, j: usize) {
70 self.0.swap(i, j);
71 self.1.swap(i, j);
72 }
73
74 fn compare(&self, i: usize, j: usize) -> Ordering {
75 let res = self.0.compare(i, j);
76 if res != Ordering::Equal {
77 return res;
78 }
79
80 self.1.compare(i, j)
81 }
82}
83
84pub fn insertion_sort<T>(container: &mut T, range: Range<usize>)
86where
87 T: Sortable + ?Sized,
88{
89 let mut i = range.start + 1;
90 while i < range.end {
91 let mut j = i;
92 while j > range.start && container.compare(j - 1, j) == Ordering::Greater {
93 container.swap(j, j - 1);
94 j -= 1;
95 }
96 i += 1;
97 }
98}
99
100fn lower_bound(container: &(impl Sortable + ?Sized), range: Range<usize>, pos: usize) -> usize {
101 let mut from = range.start;
102 let mut len = range.len();
103 while len > 0 {
104 let half = len / 2;
105 let middle = from + half;
106 if container.compare(middle, pos) == Ordering::Less {
107 from = middle + 1;
108 len -= half + 1;
109 } else {
110 len = half;
111 }
112 }
113 from
114}
115
116fn upper_bound(container: &(impl Sortable + ?Sized), range: Range<usize>, pos: usize) -> usize {
117 let mut from = range.start;
118 let mut len = range.len();
119 while len > 0 {
120 let half = len / 2;
121 let middle = from + half;
122 if container.compare(pos, middle) == Ordering::Less {
123 len = half;
124 } else {
125 from = middle + 1;
126 len -= half + 1;
127 }
128 }
129 from
130}
131
132const MERGESORT_NO_REC: usize = 16;
133
134fn in_place_merge(
135 container: &mut (impl Sortable + ?Sized),
136 from: usize,
137 mut mid: usize,
138 to: usize,
139) {
140 if from >= mid || mid >= to {
141 return;
142 }
143 if to - from == 2 {
144 if container.compare(mid, from) == Ordering::Less {
145 container.swap(from, mid)
146 }
147 return;
148 }
149
150 let first_cut;
151 let second_cut;
152
153 if mid - from > to - mid {
154 first_cut = from + (mid - from) / 2;
155 second_cut = lower_bound(container, mid..to, first_cut);
156 } else {
157 second_cut = mid + (to - mid) / 2;
158 first_cut = upper_bound(container, from..mid, second_cut);
159 }
160
161 let first2 = first_cut;
162 let middle2 = mid;
163 let last2 = second_cut;
164 if middle2 != first2 && middle2 != last2 {
165 let mut first1 = first2;
166 let mut last1 = middle2 - 1;
167 while first1 < last1 {
168 container.swap(first1, last1);
169 first1 += 1;
170 last1 -= 1;
171 }
172 first1 = middle2;
173 last1 = last2 - 1;
174 while first1 < last1 {
175 container.swap(first1, last1);
176 first1 += 1;
177 last1 -= 1;
178 }
179 first1 = first2;
180 last1 = last2 - 1;
181 while first1 < last1 {
182 container.swap(first1, last1);
183 first1 += 1;
184 last1 -= 1;
185 }
186 }
187
188 mid = first_cut + (second_cut - mid);
189 in_place_merge(container, from, first_cut, mid);
190 in_place_merge(container, mid, second_cut, to);
191}
192
193pub fn merge_sort<T>(container: &mut T, range: Range<usize>)
195where
196 T: Sortable + ?Sized,
197{
198 let length = range.len();
199
200 if length < MERGESORT_NO_REC {
202 insertion_sort(container, range);
203 return;
204 }
205
206 let mid = range.start + length / 2;
208 merge_sort(container, range.start..mid);
209 merge_sort(container, mid..range.end);
210
211 if container.compare(mid - 1, mid) != Ordering::Greater {
214 return;
215 }
216
217 in_place_merge(container, range.start, mid, range.end);
219}
220
221fn qs_helper<T>(container: &mut T, left: isize, right: isize)
224where
225 T: Sortable + ?Sized,
226{
227 if right <= left {
228 return;
229 }
230
231 if right - left >= 20 {
233 insertion_sort(container, (left as usize)..(right as usize + 1));
234 return;
235 }
236
237 {
239 let mid = left + (right - left)/2;
240 let pivot = if let Ordering::Equal | Ordering::Less = container.compare(left as usize, mid as usize) {
241 if let Ordering::Equal | Ordering::Less = container.compare(mid as usize, right as usize) {
242 mid
244 } else {
245 if let Ordering::Equal | Ordering::Less = container.compare(left as usize, right as usize) {
246 right
248 } else {
249 left
251 }
252 }
253 } else {
254 if let Ordering::Equal | Ordering::Less = container.compare(mid as usize, right as usize) {
255 if let Ordering::Equal | Ordering::Less = container.compare(left as usize, right as usize) {
256 left
258 } else {
259 right
261 }
262 } else {
263 mid
265 }
266 };
267
268 if pivot != right {
270 container.swap(pivot as usize, right as usize);
271 }
272 }
273
274 let mut i = left - 1;
275 let mut j = right;
276 let mut p = i;
277 let mut q = j;
278
279 let v = right;
280
281 loop {
282 i += 1;
283 while container.compare(i as usize, v as usize) == Ordering::Less {
284 i += 1
285 }
286
287 j -= 1;
288 while container.compare(v as usize, j as usize) == Ordering::Less {
289 if j == left {
290 break;
291 }
292 j -= 1;
293 }
294
295 if i >= j {
296 break;
297 }
298
299 container.swap(i as usize, j as usize);
300 if container.compare(i as usize, v as usize) == Ordering::Equal {
301 p += 1;
302 container.swap(p as usize, i as usize);
303 }
304 if container.compare(v as usize, j as usize) == Ordering::Equal {
305 q -= 1;
306 container.swap(j as usize, q as usize);
307 }
308 }
309
310 container.swap(i as usize, right as usize);
311 j = i - 1;
312 i += 1;
313 let mut k = left;
314 while k < p {
315 container.swap(k as usize, j as usize);
316 k += 1;
317 j -= 1;
318 }
319
320 k = right - 1;
321 while k > q {
322 container.swap(i as usize, k as usize);
323 k -= 1;
324 i += 1;
325 }
326
327 qs_helper(container, left, j);
328 qs_helper(container, i, right);
329}
330
331pub fn quick_sort<T>(container: &mut T, range: Range<usize>)
333where
334 T: Sortable + ?Sized,
335{
336 qs_helper(container, range.start as isize, range.end as isize - 1);
337}
338
339#[cfg(test)]
340mod tests {
341
342 fn ordered_vec(n: i32) -> Vec<i32> {
343 (0..n).collect()
344 }
345
346 fn rev_ordered_vec(n: i32) -> Vec<i32> {
347 (0..n).into_iter().rev().collect()
348 }
349
350 fn alternating_vec(n: i32) -> Vec<i32> {
351 let mut res = Vec::new();
352 for i in 0..n {
353 res.push(2 * i);
354 }
355 for i in 0..n {
356 res.push(2 * i + 1);
357 }
358 res
359 }
360
361 fn low_center_vec(n: i32) -> Vec<i32> {
362 let mut res = Vec::new();
363 res.extend((0..n).into_iter().rev());
364 res.extend((0..n).into_iter());
365 res
366 }
367
368 fn vectors() -> Vec<Vec<i32>> {
369 let mut result = Vec::new();
370 for i in [10i32, 20, 30, 50, 100, 500, 1000] {
371 result.push(ordered_vec(i));
372 result.push(rev_ordered_vec(i));
373 result.push(alternating_vec(i));
374 result.push(low_center_vec(i));
375 }
376 result
377 }
378
379 fn is_sorted<T: Ord>(v: impl AsRef<[T]>) -> bool {
380 v.as_ref()
381 .iter()
382 .zip(v.as_ref().iter().skip(1))
383 .all(|(a, b)| a <= b)
384 }
385
386 #[test]
387 fn quicksort_vectors() {
388 for mut v in vectors() {
389 let rng = 0..v.len();
390 super::quick_sort(v.as_mut_slice(), rng);
391 assert!(is_sorted(v));
392 }
393 }
394
395 #[test]
396 fn mergesort_vectors() {
397 for mut v in vectors() {
398 let rng = 0..v.len();
399 super::merge_sort(v.as_mut_slice(), rng);
400 assert!(is_sorted(v));
401 }
402 }
403
404 #[test]
405 fn insertionsort_vectors() {
406 for mut v in vectors() {
407 let rng = 0..v.len();
408 super::insertion_sort(v.as_mut_slice(), rng);
409 assert!(is_sorted(v));
410 }
411 }
412}