Skip to content

Commit 75c9d83

Browse files
feat: make sorting mods consistent + misc minor fixes (alexfertel#61)
Co-authored-by: Alexander González <[email protected]>
1 parent 69232d8 commit 75c9d83

24 files changed

+651
-564
lines changed

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ edition = "2018"
66
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
77

88
[dependencies]
9+
paste = "1.0.12"

src/sorting/bogo_sort.rs

+54-43
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,76 @@
1-
use super::traits::MutableSorter;
21
use crate::math::PCG32;
2+
use crate::sorting::traits::Sorter;
33
use std::time::{SystemTime, UNIX_EPOCH};
44

5-
const DEFAULT: u64 = 4294967296;
5+
const DEFAULT: u64 = 2 << 31; // 2^32
66

7-
pub struct BogoSort;
7+
fn is_sorted<T: Ord>(arr: &[T], len: usize) -> bool {
8+
if len <= 1 {
9+
return true;
10+
}
811

9-
impl BogoSort {
10-
fn is_sorted<T: Ord>(arr: &[T], len: usize) -> bool {
11-
for i in 0..len - 1 {
12-
if arr[i] > arr[i + 1] {
13-
return false;
14-
}
12+
for i in 0..len - 1 {
13+
if arr[i] > arr[i + 1] {
14+
return false;
1515
}
16-
17-
true
18-
}
19-
#[cfg(target_pointer_width = "64")]
20-
fn generate_index(range: usize, generator: &mut PCG32) -> usize {
21-
generator.get_u64() as usize % range
2216
}
2317

24-
#[cfg(not(target_pointer_width = "64"))]
25-
fn generate_index(range: usize, generator: &mut PCG32) -> usize {
26-
generator.get_u32() as usize % range
18+
true
19+
}
20+
#[cfg(target_pointer_width = "64")]
21+
fn generate_index(range: usize, generator: &mut PCG32) -> usize {
22+
generator.get_u64() as usize % range
23+
}
24+
25+
#[cfg(not(target_pointer_width = "64"))]
26+
fn generate_index(range: usize, generator: &mut PCG32) -> usize {
27+
generator.get_u32() as usize % range
28+
}
29+
30+
/**
31+
* Fisher–Yates shuffle for generating random permutation.
32+
*/
33+
fn permute_randomly<T>(arr: &mut [T], len: usize, generator: &mut PCG32) {
34+
if len <= 1 {
35+
return;
2736
}
2837

29-
/**
30-
* Fisher–Yates shuffle for generating random permutation.
31-
*/
32-
fn permute_randomly<T>(arr: &mut [T], len: usize, generator: &mut PCG32) {
33-
for i in (1..len).rev() {
34-
let j = BogoSort::generate_index(i + 1, generator);
35-
arr.swap(i, j);
36-
}
38+
for i in (1..len).rev() {
39+
let j = generate_index(i + 1, generator);
40+
arr.swap(i, j);
3741
}
3842
}
3943

40-
impl<T> MutableSorter<T> for BogoSort {
41-
fn sort(arr: &mut [T])
42-
where
43-
T: Ord,
44-
{
45-
let seed = match SystemTime::now().duration_since(UNIX_EPOCH) {
46-
Ok(duration) => duration.as_millis() as u64,
47-
Err(_) => DEFAULT,
48-
};
44+
fn bogo_sort<T: Ord>(arr: &mut [T]) {
45+
let seed = match SystemTime::now().duration_since(UNIX_EPOCH) {
46+
Ok(duration) => duration.as_millis() as u64,
47+
Err(_) => DEFAULT,
48+
};
4949

50-
let mut random_generator = PCG32::new_default(seed);
50+
let mut random_generator = PCG32::new_default(seed);
5151

52-
let arr_length = arr.len();
53-
while !BogoSort::is_sorted(arr, arr_length) {
54-
BogoSort::permute_randomly(arr, arr_length, &mut random_generator);
55-
}
52+
let arr_length = arr.len();
53+
while !is_sorted(arr, arr_length) {
54+
permute_randomly(arr, arr_length, &mut random_generator);
55+
}
56+
}
57+
58+
pub struct BogoSort;
59+
60+
impl<T> Sorter<T> for BogoSort
61+
where
62+
T: Ord + Copy,
63+
{
64+
fn sort_inplace(arr: &mut [T]) {
65+
bogo_sort(arr);
5666
}
5767
}
5868

5969
#[cfg(test)]
6070
mod tests {
61-
use super::super::traits::MutableSorter;
62-
use super::BogoSort;
71+
use crate::sorting::traits::Sorter;
72+
use crate::sorting::BogoSort;
6373

64-
sorting_tests!(BogoSort::sort, inplace);
74+
sorting_tests!(BogoSort::sort, bogo_sort);
75+
sorting_tests!(BogoSort::sort_inplace, bogo_sort, inplace);
6576
}

src/sorting/bubble_sort.rs

+28-22
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,37 @@
1-
// It sorts the array by repeatedly comparing the
2-
// adjacent elements and swapping them if they are
3-
// in the wrong order.
4-
// Time complexity is O(N^2)
5-
// Auxiliary space is O(1)
6-
use super::traits::MutableSorter;
1+
use crate::sorting::traits::Sorter;
72

8-
pub struct BubbleSort;
9-
10-
impl<T> MutableSorter<T> for BubbleSort {
11-
fn sort(array: &mut [T])
12-
where
13-
T: Ord,
14-
{
15-
for i in 0..array.len() {
16-
// Last i elements are already in place.
17-
for j in 0..array.len() - 1 - i {
18-
if array[j] > array[j + 1] {
19-
array.swap(j, j + 1);
20-
}
3+
fn bubble_sort<T: Ord>(arr: &mut [T]) {
4+
for i in 0..arr.len() {
5+
// Last i elements are already in place.
6+
for j in 0..arr.len() - 1 - i {
7+
if arr[j] > arr[j + 1] {
8+
arr.swap(j, j + 1);
219
}
2210
}
2311
}
2412
}
2513

14+
/// It sorts the array by repeatedly comparing the
15+
/// adjacent elements and swapping them if they are
16+
/// in the wrong order.
17+
/// Time complexity is O(N^2)
18+
/// Auxiliary space is O(1)
19+
pub struct BubbleSort;
20+
21+
impl<T> Sorter<T> for BubbleSort
22+
where
23+
T: Ord + Copy,
24+
{
25+
fn sort_inplace(array: &mut [T]) {
26+
bubble_sort(array);
27+
}
28+
}
29+
2630
#[cfg(test)]
2731
mod tests {
28-
use super::super::traits::MutableSorter;
29-
use super::BubbleSort;
30-
sorting_tests!(BubbleSort::sort, inplace);
32+
use crate::sorting::traits::Sorter;
33+
use crate::sorting::BubbleSort;
34+
35+
sorting_tests!(BubbleSort::sort, bubble_sort);
36+
sorting_tests!(BubbleSort::sort_inplace, bubble_sort, inplace);
3137
}

src/sorting/bucket_sort.rs

+31-38
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,54 @@
1-
/// Sort a slice using bucket sort algorithm.
2-
///
3-
/// Time complexity is `O(n + k)` on average, where `n` is the number of elements,
4-
/// `k` is the number of buckets used in process.
5-
///
6-
/// Space complexity is `O(n + k)`, as it sorts not in-place.
7-
pub fn bucket_sort(arr: &[usize]) -> Vec<usize> {
1+
use crate::sorting::insertion_sort::InsertionSort;
2+
use crate::sorting::traits::Sorter;
3+
4+
fn bucket_sort<T: Ord + Copy + Into<usize>>(arr: &mut [T]) {
85
if arr.is_empty() {
9-
return vec![];
6+
return;
107
}
118

129
let max = *arr.iter().max().unwrap();
1310
let len = arr.len();
1411
let mut buckets = vec![vec![]; len + 1];
1512

16-
for x in arr {
17-
buckets[len * *x / max].push(*x);
13+
for x in arr.iter() {
14+
buckets[len * (*x).into() / max.into()].push(*x);
1815
}
1916

2017
for bucket in buckets.iter_mut() {
21-
super::insertion_sort(bucket);
18+
InsertionSort::sort_inplace(bucket);
2219
}
2320

24-
let mut result = vec![];
21+
let mut i = 0;
2522
for bucket in buckets {
2623
for x in bucket {
27-
result.push(x);
24+
arr[i] = x;
25+
i += 1;
2826
}
2927
}
28+
}
3029

31-
result
30+
/// Sort a slice using bucket sort algorithm.
31+
///
32+
/// Time complexity is `O(n + k)` on average, where `n` is the number of elements,
33+
/// `k` is the number of buckets used in process.
34+
///
35+
/// Space complexity is `O(n + k)`, as it sorts not in-place.
36+
pub struct BucketSort;
37+
38+
impl<T> Sorter<T> for BucketSort
39+
where
40+
T: Ord + Copy + Into<usize>,
41+
{
42+
fn sort_inplace(arr: &mut [T]) {
43+
bucket_sort(arr);
44+
}
3245
}
3346

3447
#[cfg(test)]
3548
mod tests {
36-
use super::super::is_sorted;
37-
use super::*;
38-
39-
sorting_tests!(bucket_sort);
49+
use crate::sorting::traits::Sorter;
50+
use crate::sorting::BucketSort;
4051

41-
#[test]
42-
fn empty() {
43-
let arr: [usize; 0] = [];
44-
let res = bucket_sort(&arr);
45-
assert!(is_sorted(&res));
46-
}
47-
48-
#[test]
49-
fn one_element() {
50-
let arr: [usize; 1] = [4];
51-
let res = bucket_sort(&arr);
52-
assert!(is_sorted(&res));
53-
}
54-
55-
#[test]
56-
fn odd_number_of_elements() {
57-
let arr: Vec<usize> = vec![1, 21, 5, 11, 58];
58-
let res = bucket_sort(&arr);
59-
assert!(is_sorted(&res));
60-
}
52+
sorting_tests!(BucketSort::sort, bucket_sort);
53+
sorting_tests!(BucketSort::sort_inplace, bucket_sort, inplace);
6154
}

src/sorting/cocktail_shaker_sort.rs

+22-17
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
pub fn cocktail_shaker_sort<T: Ord>(arr: &mut [T]) {
1+
use crate::sorting::traits::Sorter;
2+
3+
fn cocktail_shaker_sort<T: Ord>(arr: &mut [T]) {
24
let len = arr.len();
35

46
if len == 0 {
@@ -34,23 +36,26 @@ pub fn cocktail_shaker_sort<T: Ord>(arr: &mut [T]) {
3436
}
3537
}
3638

37-
#[cfg(test)]
38-
mod tests {
39-
use super::*;
40-
41-
sorting_tests!(cocktail_shaker_sort, inplace);
39+
pub struct CocktailShakerSort;
4240

43-
#[test]
44-
fn empty() {
45-
let mut arr = Vec::<i32>::new();
46-
cocktail_shaker_sort(&mut arr);
47-
assert_eq!(arr, vec![]);
41+
impl<T> Sorter<T> for CocktailShakerSort
42+
where
43+
T: Ord + Copy,
44+
{
45+
fn sort_inplace(arr: &mut [T]) {
46+
cocktail_shaker_sort(arr);
4847
}
48+
}
4949

50-
#[test]
51-
fn one_element() {
52-
let mut arr = vec![1];
53-
cocktail_shaker_sort(&mut arr);
54-
assert_eq!(arr, vec![1]);
55-
}
50+
#[cfg(test)]
51+
mod tests {
52+
use crate::sorting::traits::Sorter;
53+
use crate::sorting::CocktailShakerSort;
54+
55+
sorting_tests!(CocktailShakerSort::sort, cocktail_shaker_sort);
56+
sorting_tests!(
57+
CocktailShakerSort::sort_inplace,
58+
cocktail_shaker_sort,
59+
inplace
60+
);
5661
}

0 commit comments

Comments
 (0)