Skip to content

Instantly share code, notes, and snippets.

@cbzehner
Created March 12, 2018 02:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cbzehner/e3f899f85a78117ee54f72a47ab28ccd to your computer and use it in GitHub Desktop.
Save cbzehner/e3f899f85a78117ee54f72a47ab28ccd to your computer and use it in GitHub Desktop.
An implementation of Merge Sort in Rust (with a little help from my friends!)
/// Sorts a slice in-place-ish with mergesort.
/// Time Complexity: O(n * log(n))
/// Space Complexity: O(n)
///
/// ```
/// use merge_sort::merge_sort;
///
/// let mut example = [1,4,2,5,3];
///
/// merge_sort(&mut example);
/// assert_eq!(example, [1,2,3,4,5]);
/// ```
pub fn merge_sort<T: Copy + PartialOrd>(input: &mut [T]) {
let length = input.len();
// Base case
if length < 2 {
return;
}
let mut merged = Vec::with_capacity(length);
// New code block to enforce "left" and "right" lifetimes, which otherwise
// would continue ownership of "merged", preventing moving the values back
// to input.
{
// Divide the input in half and sort each half recursively before re-merging.
let (left, right) = input.split_at_mut(length / 2);
merge_sort(left);
merge_sort(right);
let mut left_iter = left.iter().peekable();
let mut right_iter = right.iter().peekable();
// Iterate through left and right sides finding the next lowest value
while let (Some(&l), Some(&r)) = (left_iter.peek(), right_iter.peek()) {
if *r < *l {
merged.push(*(right_iter.next().unwrap()));
} else {
merged.push(*(left_iter.next().unwrap()));
}
}
// If any values remain in left, push them onto merged
for l in left_iter {
merged.push(*l);
}
// If any values remain in right, push them onto merged
for r in right_iter {
merged.push(*r);
}
}
// Copy the values from merged back over to the input
assert!(
merged.len() == length,
"All elements from the input should be included in the sorted output"
);
for n in 0..length {
input[n] = merged[n];
}
}
#[cfg(test)]
mod tests {
use merge_sort;
#[test]
fn it_works() {
let mut example = [4, 3];
merge_sort(&mut example);
assert_eq!(example, [3, 4]);
}
#[test]
fn already_sorted() {
let mut example = [2, 3, 4, 5];
merge_sort(&mut example);
assert_eq!(example, [2, 3, 4, 5]);
}
#[test]
fn base_case() {
let mut example = [3];
merge_sort(&mut example);
assert_eq!(example, [3]);
}
#[test]
fn totally_backwards() {
let mut example = [100, 90, 50, 14, 9, 7, 3];
merge_sort(&mut example);
assert_eq!(example, [3, 7, 9, 14, 50, 90, 100]);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment