diff --git a/DIRECTORY.md b/DIRECTORY.md index e0fc47377c5..720130b66bc 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -381,6 +381,7 @@ * [Sleep Sort](https://github.com/TheAlgorithms/Rust/blob/master/src/sorting/sleep_sort.rs) * [Sort Utils](https://github.com/TheAlgorithms/Rust/blob/master/src/sorting/sort_utils.rs) * [Stooge Sort](https://github.com/TheAlgorithms/Rust/blob/master/src/sorting/stooge_sort.rs) + * [Strand Sort](https://github.com/TheAlgorithms/Rust/blob/master/src/sorting/strand_sort.rs) * [Tim Sort](https://github.com/TheAlgorithms/Rust/blob/master/src/sorting/tim_sort.rs) * [Tree Sort](https://github.com/TheAlgorithms/Rust/blob/master/src/sorting/tree_sort.rs) * [Wave Sort](https://github.com/TheAlgorithms/Rust/blob/master/src/sorting/wave_sort.rs) diff --git a/src/sorting/mod.rs b/src/sorting/mod.rs index 79be2b0b9e6..dbd91fd8af3 100644 --- a/src/sorting/mod.rs +++ b/src/sorting/mod.rs @@ -29,6 +29,7 @@ mod sleep_sort; #[cfg(test)] mod sort_utils; mod stooge_sort; +mod strand_sort; mod tim_sort; mod tree_sort; mod wave_sort; @@ -65,6 +66,7 @@ pub use self::selection_sort::selection_sort; pub use self::shell_sort::shell_sort; pub use self::sleep_sort::sleep_sort; pub use self::stooge_sort::stooge_sort; +pub use self::strand_sort::strand_sort; pub use self::tim_sort::tim_sort; pub use self::tree_sort::tree_sort; pub use self::wave_sort::wave_sort; diff --git a/src/sorting/strand_sort.rs b/src/sorting/strand_sort.rs new file mode 100644 index 00000000000..9d23ae2ad66 --- /dev/null +++ b/src/sorting/strand_sort.rs @@ -0,0 +1,108 @@ +pub fn strand_sort(arr: &mut [T]) { + if arr.len() <= 1 { + return; + } + + let mut result: Vec = Vec::new(); + let mut input: Vec = arr.to_vec(); + + while !input.is_empty() { + let mut sublist: Vec = Vec::new(); + let mut leftovers: Vec = Vec::with_capacity(input.len()); + + for item in input { + if sublist.is_empty() || item >= *sublist.last().unwrap() { + sublist.push(item); + } else { + leftovers.push(item); + } + } + + result = merge(result, sublist); + input = leftovers; + } + + arr.clone_from_slice(&result); +} + +fn merge(left: Vec, right: Vec) -> Vec { + let mut merged = Vec::with_capacity(left.len() + right.len()); + let mut left_iter = left.into_iter().peekable(); + let mut right_iter = right.into_iter().peekable(); + + while let (Some(l), Some(r)) = (left_iter.peek(), right_iter.peek()) { + if l <= r { + merged.push(left_iter.next().unwrap()); + } else { + merged.push(right_iter.next().unwrap()); + } + } + + merged.extend(left_iter); + merged.extend(right_iter); + + merged +} + +#[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(); + strand_sort(&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(); + strand_sort(&mut res); + assert!(is_sorted(&res) && have_same_elements(&res, &cloned)); + } + + #[test] + fn empty() { + let mut res = Vec::::new(); + let cloned = res.clone(); + strand_sort(&mut res); + assert!(is_sorted(&res) && have_same_elements(&res, &cloned)); + } + + #[test] + fn one_element() { + let mut res = vec![1]; + let cloned = res.clone(); + strand_sort(&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(); + strand_sort(&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(); + strand_sort(&mut res); + assert!(is_sorted(&res) && have_same_elements(&res, &cloned)); + } + + #[test] + fn duplicates() { + let mut res = vec![4, 2, 4, 3, 2, 1, 4]; + let cloned = res.clone(); + strand_sort(&mut res); + assert!(is_sorted(&res) && have_same_elements(&res, &cloned)); + } +}