Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions DIRECTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@
* [Insertion Sort](https://github.com/TheAlgorithms/Rust/blob/master/src/sorting/insertion_sort.rs)
* [Intro Sort](https://github.com/TheAlgorithms/Rust/blob/master/src/sorting/intro_sort.rs)
* [Merge Sort](https://github.com/TheAlgorithms/Rust/blob/master/src/sorting/merge_sort.rs)
* [Merge Sort Inplace](https://github.com/TheAlgorithms/Rust/blob/master/src/sorting/merge_sort_inplace.rs)
* [Odd Even Sort](https://github.com/TheAlgorithms/Rust/blob/master/src/sorting/odd_even_sort.rs)
* [Pancake Sort](https://github.com/TheAlgorithms/Rust/blob/master/src/sorting/pancake_sort.rs)
* [Patience Sort](https://github.com/TheAlgorithms/Rust/blob/master/src/sorting/patience_sort.rs)
Expand Down
169 changes: 169 additions & 0 deletions src/sorting/merge_sort_inplace.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
fn merge<T: Ord>(array: &mut [T], mid: usize) {
let len = array.len();
let mut left = 0;
let mut right = mid;

while left < right && right < len {
if array[left] < array[right] {
left += 1;
} else {
let tmp = right;
while right < len && array[left] > array[right] {
right += 1;
}
let rotate_mid = tmp - left;
let slice = &mut array[left..right];
slice.rotate_left(rotate_mid);
left += right - tmp;
}
}
}

pub fn top_down_merge_sort_inplace<T: Ord>(arr: &mut [T]) {
if arr.len() > 1 {
let mid = arr.len() / 2;
// Sort the left half recursively.
top_down_merge_sort_inplace(&mut arr[..mid]);
// Sort the right half recursively.
top_down_merge_sort_inplace(&mut arr[mid..]);
// Combine the two halves.
merge(arr, mid);
}
}

pub fn bottom_up_merge_sort_inplace<T: Ord>(a: &mut [T]) {
if a.len() > 1 {
let len: usize = a.len();
let mut sub_array_size: usize = 1;
while sub_array_size < len {
let mut start_index: usize = 0;
// still have more than one sub-arrays to merge
while len - start_index > sub_array_size {
let end_idx: usize = if start_index + 2 * sub_array_size > len {
len
} else {
start_index + 2 * sub_array_size
};
// merge a[start_index..start_index+sub_array_size] and a[start_index+sub_array_size..end_idx]
// NOTE: mid is a relative index number starting from `start_index`
merge(&mut a[start_index..end_idx], sub_array_size);
// update `start_index` to merge the next sub-arrays
start_index = end_idx;
}
sub_array_size *= 2;
}
}
}

#[cfg(test)]
mod tests {
#[cfg(test)]
mod top_down_merge_sort {
use super::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();
top_down_merge_sort_inplace(&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();
top_down_merge_sort_inplace(&mut res);
assert!(is_sorted(&res) && have_same_elements(&res, &cloned));
}

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

#[test]
fn one_element() {
let mut res = vec![1];
let cloned = res.clone();
top_down_merge_sort_inplace(&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();
top_down_merge_sort_inplace(&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();
top_down_merge_sort_inplace(&mut res);
assert!(is_sorted(&res) && have_same_elements(&res, &cloned));
}
}

#[cfg(test)]
mod bottom_up_merge_sort {
use super::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();
bottom_up_merge_sort_inplace(&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();
bottom_up_merge_sort_inplace(&mut res);
assert!(is_sorted(&res) && have_same_elements(&res, &cloned));
}

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

#[test]
fn one_element() {
let mut res = vec![1];
let cloned = res.clone();
bottom_up_merge_sort_inplace(&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();
bottom_up_merge_sort_inplace(&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();
bottom_up_merge_sort_inplace(&mut res);
assert!(is_sorted(&res) && have_same_elements(&res, &cloned));
}
}
}
4 changes: 3 additions & 1 deletion src/sorting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ mod heap_sort;
mod insertion_sort;
mod intro_sort;
mod merge_sort;
mod merge_sort_inplace;
mod odd_even_sort;
mod pancake_sort;
mod patience_sort;
Expand Down Expand Up @@ -54,6 +55,8 @@ pub use self::insertion_sort::insertion_sort;
pub use self::intro_sort::intro_sort;
pub use self::merge_sort::bottom_up_merge_sort;
pub use self::merge_sort::top_down_merge_sort;
pub use self::merge_sort_inplace::bottom_up_merge_sort_inplace;
pub use self::merge_sort_inplace::top_down_merge_sort_inplace;
pub use self::odd_even_sort::odd_even_sort;
pub use self::pancake_sort::pancake_sort;
pub use self::patience_sort::patience_sort;
Expand All @@ -69,7 +72,6 @@ pub use self::tim_sort::tim_sort;
pub use self::tree_sort::tree_sort;
pub use self::wave_sort::wave_sort;
pub use self::wiggle_sort::wiggle_sort;

#[cfg(test)]
use std::cmp;

Expand Down