Skip to content

Commit

Permalink
Add 3-way quick sort (#532)
Browse files Browse the repository at this point in the history
  • Loading branch information
suzp1984 authored Oct 2, 2023
1 parent 66d6d52 commit 172c175
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/sorting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ mod pancake_sort;
mod patience_sort;
mod pigeonhole_sort;
mod quick_sort;
mod quick_sort_3_ways;
mod radix_sort;
mod selection_sort;
mod shell_sort;
Expand Down Expand Up @@ -45,6 +46,7 @@ pub use self::pancake_sort::pancake_sort;
pub use self::patience_sort::patience_sort;
pub use self::pigeonhole_sort::pigeonhole_sort;
pub use self::quick_sort::{partition, quick_sort};
pub use self::quick_sort_3_ways::quick_sort_3_ways;
pub use self::radix_sort::radix_sort;
pub use self::selection_sort::selection_sort;
pub use self::shell_sort::shell_sort;
Expand Down
103 changes: 103 additions & 0 deletions src/sorting/quick_sort_3_ways.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
use std::cmp::{Ord, Ordering};

fn _quick_sort_3_ways<T: Ord>(arr: &mut [T], lo: isize, hi: isize) {
if lo >= hi {
return;
}

let mut lt = lo; // arr[lo+1, lt] < v
let mut gt = hi + 1; // arr[gt, r] > v
let mut i = lo + 1; // arr[lt + 1, i) == v

while i < gt {
match arr[i as usize].cmp(&arr[lo as usize]) {
Ordering::Less => {
arr.swap(i as usize, (lt + 1) as usize);
i += 1;
lt += 1;
}
Ordering::Greater => {
arr.swap(i as usize, (gt - 1) as usize);
gt -= 1;
}
Ordering::Equal => {
i += 1;
}
}
}

arr.swap(lo as usize, lt as usize);

_quick_sort_3_ways(arr, lo, lt - 1);
_quick_sort_3_ways(arr, gt, hi);
}

pub fn quick_sort_3_ways<T: Ord>(arr: &mut [T]) {
let len = arr.len();
if len > 1 {
_quick_sort_3_ways(arr, 0, (len - 1) as isize);
}
}

#[cfg(test)]
mod tests {
use super::*;
use crate::sorting::have_same_elements;
use crate::sorting::is_sorted;

#[test]
fn basic() {
let mut res = vec![10, 8, 4, 3, 1, 9, 2, 7, 5, 6];
let cloned = res.clone();
quick_sort_3_ways(&mut res);
assert!(is_sorted(&res) && have_same_elements(&res, &cloned));
}

#[test]
fn basic_string() {
let mut res = vec!["a", "bb", "d", "cc"];
let cloned = res.clone();
quick_sort_3_ways(&mut res);
assert!(is_sorted(&res) && have_same_elements(&res, &cloned));
}

#[test]
fn empty() {
let mut res = Vec::<u8>::new();
let cloned = res.clone();
quick_sort_3_ways(&mut res);
assert!(is_sorted(&res) && have_same_elements(&res, &cloned));
}

#[test]
fn one_element() {
let mut res = vec![1];
let cloned = res.clone();
quick_sort_3_ways(&mut res);
assert!(is_sorted(&res) && have_same_elements(&res, &cloned));
}

#[test]
fn pre_sorted() {
let mut res = vec![1, 2, 3, 4];
let cloned = res.clone();
quick_sort_3_ways(&mut res);
assert!(is_sorted(&res) && have_same_elements(&res, &cloned));
}

#[test]
fn reverse_sorted() {
let mut res = vec![4, 3, 2, 1];
let cloned = res.clone();
quick_sort_3_ways(&mut res);
assert!(is_sorted(&res) && have_same_elements(&res, &cloned));
}

#[test]
fn repeated_elements() {
let mut res = vec![2, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2];
let cloned = res.clone();
quick_sort_3_ways(&mut res);
assert!(is_sorted(&res) && have_same_elements(&res, &cloned));
}
}

0 comments on commit 172c175

Please sign in to comment.