algods/sort/
quick_sort.rs

1#[cfg(test)]
2mod unit_test;
3use rand::seq::SliceRandom;
4use rand::thread_rng;
5use std::cmp::Ordering;
6use std::mem::replace;
7
8/// Implementation of quick sort algorithm
9#[derive(Debug)]
10pub struct QuickSort<T> {
11    vec: Vec<T>,
12    // QuickSort is unstable in the sense that
13    // items with equal keys can be exchanged ?
14}
15
16impl<T: Ord + Clone> QuickSort<T> {
17    /// Creates a new quick sort instance from a `Vec`.
18    /// ```
19    /// use algods::sort::QuickSort;
20    /// let ms = QuickSort::init(vec![100, 20, 9, 17]);
21    /// ```
22    pub fn init(v: Vec<T>) -> Self {
23        Self { vec: v }
24    }
25
26    fn partition(&mut self, low: usize, high: usize) -> usize {
27        // Finds a partitioning index j, i.e such that elements at the left of index j
28        // are no greater than element j and elements at the right of index j are no larger
29        // than element j.
30        // run time complexity O(N)
31        let mut i = low + 1;
32        let mut j = high;
33        loop {
34            // find item on left to swap
35            while self.vec[i] <= self.vec[low] {
36                i += 1;
37                if i >= high {
38                    break;
39                }
40            }
41            // find item on right to swap
42            while self.vec[low] <= self.vec[j] {
43                j -= 1;
44                if j <= low {
45                    break;
46                }
47            }
48            // check if positions/pointers cross
49            if i >= j {
50                break;
51            }
52            // exchange i^th and j^th object to respect partitioning
53            let n = self.vec[j].clone();
54            self.vec[j] = replace(&mut self.vec[i], n);
55        }
56        // swap with partitioning item
57        let n = self.vec[j].clone();
58        self.vec[j] = replace(&mut self.vec[low], n);
59        j
60    }
61
62    fn sort(&mut self) {
63        // shuffle garantees performance ?
64        let mut rng = thread_rng();
65        self.vec.shuffle(&mut rng);
66        self.recursive_sort(0, self.vec.len() - 1);
67    }
68
69    fn recursive_sort(&mut self, low: usize, high: usize) {
70        if high <= low {
71            return;
72        }
73        let j: usize = self.partition(low, high);
74        if j >= 1 && j < self.vec.len() - 1 {
75            self.recursive_sort(low, j - 1);
76            self.recursive_sort(j + 1, high);
77        } else if j == 0 {
78            self.recursive_sort(j + 1, high);
79        } else {
80            self.recursive_sort(low, j - 1);
81        }
82    }
83
84    /// Sorts a `Vec` using quick sort algorithm. It moves the QuickSort.
85    /// ```
86    /// use algods::sort::QuickSort;
87    /// let mut v = vec![100, 20, 9, 17];
88    /// let qs = QuickSort::init(v.clone());
89    /// v.sort_unstable();
90    /// assert_eq!(qs.into_sorted_vec(), v);
91    /// ```   
92    pub fn into_sorted_vec(mut self) -> Vec<T> {
93        self.sort();
94        self.vec
95    }
96
97    /// Selects the kth largest element in the `Vec` instantiating the QuickSort using the
98    /// quick select algorithm
99    /// ```
100    /// use algods::sort::QuickSort;
101    /// let mut qs = QuickSort::init(vec![30, 13, 90, 50, 47, 100]);
102    /// assert_eq!(qs.select(3), 50);
103    /// ```
104    pub fn select(&mut self, k: usize) -> T {
105        // Selects the k^th largest element in self.vec (quick select algorithm)
106        // in linear time on average for median (k = N/2)
107        let mut rng = thread_rng();
108        self.vec.shuffle(&mut rng);
109        let mut low = 0;
110        let mut high = self.vec.len() - 1;
111        while high > low {
112            let j = self.partition(low, high);
113            match j.cmp(&k) {
114                // the k^th largest is on the right of element j
115                Ordering::Less => low = j + 1,
116                // the k^th largest is on the left of element j
117                Ordering::Greater => high = j - 1,
118                // j = k, we are done
119                Ordering::Equal => return self.vec[k].clone(),
120            }
121        }
122        self.vec[k].clone()
123    }
124}