Rust Program to Implement Merge Sort

Rust Program to Implement Merge Sort

Merge Sort is a powerful and efficient sorting algorithm that uses the divide-and-conquer approach to sort arrays. Unlike simple algorithms like Insertion or Bubble Sort, Merge Sort splits the array into smaller parts, sorts them individually, and then merges the sorted parts back together. This approach ensures a consistent performance, making it suitable for larger datasets where efficiency is important. Learning Merge Sort in Rust not only helps beginners understand a more advanced sorting technique but also provides exposure to recursion, array manipulation, and ownership concepts in Rust.

Pluralsight Logo
Accelerate your tech career
with hands-on learning.
Whether you're a tech newbie or a total pro,
get the skills and confidence to land your next move.
Start 10-Day Free Trial

In practical scenarios, Merge Sort is often used in software systems where stability in sorting is essential. Stability means that the relative order of equal elements is preserved. Understanding Merge Sort builds a strong foundation for other recursive algorithms and introduces beginners to how efficient algorithms can dramatically reduce runtime compared to simpler methods.

Program 1: Basic Merge Sort Using Recursion

This program demonstrates the classic recursive Merge Sort for integers in Rust. The array is divided into halves recursively until individual elements remain, which are then merged in sorted order.

fn merge_sort(arr: &mut [i32]) {

    let n = arr.len();

    if n <= 1 {
        return;
    }

    let mid = n / 2;
    let mut left = arr[..mid].to_vec();
    let mut right = arr[mid..].to_vec();

    merge_sort(&mut left);
    merge_sort(&mut right);

    let mut i = 0;
    let mut j = 0;
    let mut k = 0;

    while i < left.len() && j < right.len() {

        if left[i] <= right[j] {
            arr[k] = left[i];
            i += 1;
        } else {
            arr[k] = right[j];
            j += 1;
        }

        k += 1;

    }

    while i < left.len() {
        arr[k] = left[i];
        i += 1;
        k += 1;
    }

    while j < right.len() {
        arr[k] = right[j];
        j += 1;
        k += 1;
    }

}

fn main() {

    let mut numbers = [38, 27, 43, 3, 9, 82, 10];
    println!("Original array: {:?}", numbers);

    merge_sort(&mut numbers);
    println!("Sorted array: {:?}", numbers);

}

This program shows how recursion divides the problem into smaller parts. Beginners can see how the merge step combines the sorted halves, reinforcing both recursive thinking and array manipulation skills.

Program 2: Merge Sort for Floating-Point Numbers

Merge Sort works not only for integers but also for floating-point numbers. This version demonstrates sorting decimals.

fn merge_sort_floats(arr: &mut [f64]) {

    let n = arr.len();

    if n <= 1 {
        return;
    }

    let mid = n / 2;
    let mut left = arr[..mid].to_vec();
    let mut right = arr[mid..].to_vec();

    merge_sort_floats(&mut left);
    merge_sort_floats(&mut right);

    let mut i = 0;
    let mut j = 0;
    let mut k = 0;

    while i < left.len() && j < right.len() {

        if left[i] <= right[j] {
            arr[k] = left[i];
            i += 1;
        } else {
            arr[k] = right[j];
            j += 1;
        }

        k += 1;

    }

    while i < left.len() {
        arr[k] = left[i];
        i += 1;
        k += 1;
    }

    while j < right.len() {
        arr[k] = right[j];
        j += 1;
        k += 1;
    }

}

fn main() {

    let mut numbers = [3.4, 2.1, 5.6, 1.2, 4.9];
    println!("Original array: {:?}", numbers);

    merge_sort_floats(&mut numbers);
    println!("Sorted array: {:?}", numbers);

}

This program illustrates that Merge Sort can handle multiple numeric types, making it a versatile tool for beginners learning type handling in Rust.

Program 3: Merge Sort Using Generics

Rust allows generic programming, letting you write a single merge sort function that works for any type implementing the Ord trait.

fn merge_sort_generic<T: Ord + Clone>(arr: &mut [T]) {

    let n = arr.len();

    if n <= 1 {
        return;
    }

    let mid = n / 2;
    let mut left = arr[..mid].to_vec();
    let mut right = arr[mid..].to_vec();

    merge_sort_generic(&mut left);
    merge_sort_generic(&mut right);

    let mut i = 0;
    let mut j = 0;
    let mut k = 0;

    while i < left.len() && j < right.len() {

        if left[i] <= right[j] {
            arr[k] = left[i].clone();
            i += 1;
        } else {
            arr[k] = right[j].clone();
            j += 1;
        }

        k += 1;

    }

    while i < left.len() {
        arr[k] = left[i].clone();
        i += 1;
        k += 1;
    }

    while j < right.len() {
        arr[k] = right[j].clone();
        j += 1;
        k += 1;
    }

}

fn main() {

    let mut int_arr = [12, 11, 13, 5, 6];
    let mut char_arr = ['d', 'a', 'c', 'b'];

    println!("Original integer array: {:?}", int_arr);
    merge_sort_generic(&mut int_arr);
    println!("Sorted integer array: {:?}", int_arr);

    println!("Original char array: {:?}", char_arr);
    merge_sort_generic(&mut char_arr);
    println!("Sorted char array: {:?}", char_arr);

}

Generics make the code reusable for multiple data types. Beginners learn how Rust ensures type safety while providing flexibility in functions.

Program 4: Merge Sort with Debug Prints

This version adds debug statements to help beginners understand how arrays are split and merged during recursion.

fn merge_sort_debug(arr: &mut [i32]) {

    let n = arr.len();

    if n <= 1 {
        return;
    }

    println!("Splitting: {:?}", arr);

    let mid = n / 2;
    let mut left = arr[..mid].to_vec();
    let mut right = arr[mid..].to_vec();

    merge_sort_debug(&mut left);
    merge_sort_debug(&mut right);

    let mut i = 0;
    let mut j = 0;
    let mut k = 0;

    while i < left.len() && j < right.len() {

        if left[i] <= right[j] {
            arr[k] = left[i];
            i += 1;
        } else {
            arr[k] = right[j];
            j += 1;
        }

        k += 1;

    }

    while i < left.len() {
        arr[k] = left[i];
        i += 1;
        k += 1;
    }

    while j < right.len() {
        arr[k] = right[j];
        j += 1;
        k += 1;
    }

    println!("Merged: {:?}", arr);

}

fn main() {

    let mut numbers = [7, 2, 6, 3, 9];
    println!("Original array: {:?}", numbers);

    merge_sort_debug(&mut numbers);
    println!("Sorted array: {:?}", numbers);

}

Debug prints allow beginners to visualize how recursion divides the array and how the merge step reconstructs the sorted array.

Program 5: Merge Sort for Strings

Merge Sort can also be applied to strings. This example sorts an array of words alphabetically.

fn merge_sort_strings(arr: &mut [&str]) {

    let n = arr.len();

    if n <= 1 {
        return;
    }

    let mid = n / 2;
    let mut left = arr[..mid].to_vec();
    let mut right = arr[mid..].to_vec();

    merge_sort_strings(&mut left);
    merge_sort_strings(&mut right);

    let mut i = 0;
    let mut j = 0;
    let mut k = 0;

    while i < left.len() && j < right.len() {

        if left[i] <= right[j] {
            arr[k] = left[i];
            i += 1;
        } else {
            arr[k] = right[j];
            j += 1;
        }

        k += 1;

    }

    while i < left.len() {
        arr[k] = left[i];
        i += 1;
        k += 1;
    }

    while j < right.len() {
        arr[k] = right[j];
        j += 1;
        k += 1;
    }

}

fn main() {

    let mut words = ["banana", "apple", "grape", "cherry"];
    println!("Original array: {:?}", words);

    merge_sort_strings(&mut words);
    println!("Sorted array: {:?}", words);

}

Sorting strings demonstrates the flexibility of Merge Sort, showing beginners that the algorithm is not limited to numbers.

Frequently Asked Questions (FAQ)

This section clears common doubts about Merge Sort in Rust.

Q1: Why is Merge Sort useful for beginners?
It teaches divide-and-conquer techniques and recursion, foundational concepts in programming.

Q2: Is Merge Sort faster than Insertion or Bubble Sort?
Yes, Merge Sort has a consistent O(n log n) complexity, making it much faster for large datasets.

Q3: Can Merge Sort work with strings in Rust?
Yes, as long as the type implements the Ord trait.

Q4: What is the main idea behind Merge Sort?
Split the array into halves recursively, sort each half, and merge them in order.

Q5: When should I use Merge Sort?
It’s best for large arrays or when stable sorting is required.

Conclusion

Merge Sort is a highly efficient and versatile sorting algorithm that helps beginners understand recursion, array manipulation, and Rust’s type system. By exploring multiple implementations—including generics, floats, strings, and debug versions—learners gain practical experience with recursion and safe array handling. Practicing Merge Sort lays a solid foundation for understanding other advanced sorting algorithms like Quick Sort and Heap Sort. With consistent practice, beginners can confidently tackle complex data processing tasks in Rust.

Scroll to Top