tinystd/sort/quick.rs
1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License at
4//
5// http://www.apache.org/licenses/LICENSE-2.0
6//
7// Unless required by applicable law or agreed to in writing, software
8// distributed under the License is distributed on an "AS IS" BASIS,
9// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10// See the License for the specific language governing permissions and
11// limitations under the License.
12
13//! [Quicksort][1]. Not bad.
14//! [1]: https://en.wikipedia.org/wiki/Quicksort
15use super::*;
16
17pub struct Quick;
18
19/// The well-known recursive sorting algorithm
20pub fn quicksort<T: Ord>(slice: &mut [T]) {
21 match slice.len() {
22 0 | 1 => return,
23 2 => {
24 if slice[0] > slice[1] {
25 slice.swap(0, 1);
26 return;
27 }
28 }
29 _ => (),
30 }
31
32 let (pivot, rest) = slice.split_first_mut().expect("slice must be non-empty");
33 let mut left = 0;
34 let mut right = rest.len() - 1;
35
36 while left <= right {
37 if &rest[left] <= pivot {
38 left += 1;
39 } else if &rest[right] > pivot {
40 if right == 0 {
41 break;
42 }
43 right -= 1;
44 } else {
45 rest.swap(left, right);
46 left += 1;
47 if right == 0 {
48 break;
49 };
50 right -= 1;
51 }
52 }
53
54 // set the pivot to it's correct location
55 let left = left + 1;
56 slice.swap(0, left - 1);
57
58 // recurse
59 let (left, right) = slice.split_at_mut(left - 1);
60 quicksort(left);
61 quicksort(&mut right[1..]);
62}
63
64impl Sorter for Quick {
65 fn sort<T>(&self, slice: &mut [T])
66 where
67 T: Ord,
68 {
69 quicksort(slice);
70 }
71}
72
73#[cfg(test)]
74mod tests {
75 use super::*;
76
77 #[test]
78 fn it_works() {
79 let mut items = vec![4, 2, 3, 1];
80 Quick.sort(&mut items);
81 assert_eq!(items, &[1, 2, 3, 4]);
82 }
83}