Skip to content

Commit 1667f9b

Browse files
committed
Add Strand Sort Algorithm
1 parent a84b940 commit 1667f9b

2 files changed

Lines changed: 120 additions & 0 deletions

File tree

src/sorting/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ mod sleep_sort;
2929
#[cfg(test)]
3030
mod sort_utils;
3131
mod stooge_sort;
32+
mod strand_sort;
3233
mod tim_sort;
3334
mod tree_sort;
3435
mod wave_sort;
@@ -65,6 +66,7 @@ pub use self::selection_sort::selection_sort;
6566
pub use self::shell_sort::shell_sort;
6667
pub use self::sleep_sort::sleep_sort;
6768
pub use self::stooge_sort::stooge_sort;
69+
pub use self::strand_sort::strand_sort;
6870
pub use self::tim_sort::tim_sort;
6971
pub use self::tree_sort::tree_sort;
7072
pub use self::wave_sort::wave_sort;

src/sorting/strand_sort.rs

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
pub fn strand_sort<T: Ord + Clone>(arr: &mut [T]) {
2+
if arr.len() <= 1 {
3+
return;
4+
}
5+
6+
let mut result: Vec<T> = Vec::new();
7+
let mut input: Vec<T> = arr.to_vec();
8+
9+
while !input.is_empty() {
10+
let mut sublist: Vec<T> = Vec::new();
11+
let mut leftovers: Vec<T> = Vec::with_capacity(input.len());
12+
13+
for item in input {
14+
if sublist.is_empty() || item >= *sublist.last().unwrap() {
15+
sublist.push(item);
16+
} else {
17+
leftovers.push(item);
18+
}
19+
}
20+
21+
result = merge(result, sublist);
22+
input = leftovers;
23+
}
24+
25+
arr.clone_from_slice(&result);
26+
}
27+
28+
fn merge<T: Ord + Clone>(left: Vec<T>, right: Vec<T>) -> Vec<T> {
29+
let mut merged = Vec::with_capacity(left.len() + right.len());
30+
let mut left_iter = left.into_iter().peekable();
31+
let mut right_iter = right.into_iter().peekable();
32+
33+
loop {
34+
match (left_iter.peek(), right_iter.peek()) {
35+
(Some(l), Some(r)) => {
36+
if l <= r {
37+
merged.push(left_iter.next().unwrap());
38+
} else {
39+
merged.push(right_iter.next().unwrap());
40+
}
41+
}
42+
(Some(_), None) => {
43+
merged.extend(left_iter);
44+
break;
45+
}
46+
(None, Some(_)) => {
47+
merged.extend(right_iter);
48+
break;
49+
}
50+
(None, None) => break,
51+
}
52+
}
53+
54+
merged
55+
}
56+
57+
#[cfg(test)]
58+
mod tests {
59+
use super::*;
60+
use crate::sorting::have_same_elements;
61+
use crate::sorting::is_sorted;
62+
63+
#[test]
64+
fn basic() {
65+
let mut res = vec![10, 8, 4, 3, 1, 9, 2, 7, 5, 6];
66+
let cloned = res.clone();
67+
strand_sort(&mut res);
68+
assert!(is_sorted(&res) && have_same_elements(&res, &cloned));
69+
}
70+
71+
#[test]
72+
fn basic_string() {
73+
let mut res = vec!["a", "bb", "d", "cc"];
74+
let cloned = res.clone();
75+
strand_sort(&mut res);
76+
assert!(is_sorted(&res) && have_same_elements(&res, &cloned));
77+
}
78+
79+
#[test]
80+
fn empty() {
81+
let mut res = Vec::<u8>::new();
82+
let cloned = res.clone();
83+
strand_sort(&mut res);
84+
assert!(is_sorted(&res) && have_same_elements(&res, &cloned));
85+
}
86+
87+
#[test]
88+
fn one_element() {
89+
let mut res = vec![1];
90+
let cloned = res.clone();
91+
strand_sort(&mut res);
92+
assert!(is_sorted(&res) && have_same_elements(&res, &cloned));
93+
}
94+
95+
#[test]
96+
fn pre_sorted() {
97+
let mut res = vec![1, 2, 3, 4];
98+
let cloned = res.clone();
99+
strand_sort(&mut res);
100+
assert!(is_sorted(&res) && have_same_elements(&res, &cloned));
101+
}
102+
103+
#[test]
104+
fn reverse_sorted() {
105+
let mut res = vec![4, 3, 2, 1];
106+
let cloned = res.clone();
107+
strand_sort(&mut res);
108+
assert!(is_sorted(&res) && have_same_elements(&res, &cloned));
109+
}
110+
111+
#[test]
112+
fn duplicates() {
113+
let mut res = vec![4, 2, 4, 3, 2, 1, 4];
114+
let cloned = res.clone();
115+
strand_sort(&mut res);
116+
assert!(is_sorted(&res) && have_same_elements(&res, &cloned));
117+
}
118+
}

0 commit comments

Comments
 (0)