Rust Program to Implement Quick Sort

Rust Program to Implement Quick Sort

Quick Sort is one of the most popular and efficient sorting algorithms used in programming. It follows the divide-and-conquer principle, which means it breaks the problem into smaller subproblems, solves them independently, and combines the results. Unlike simpler algorithms like Bubble Sort or Insertion Sort, Quick Sort is faster on average, especially for large datasets, making it a valuable skill for any beginner learning Rust. Understanding Quick Sort also introduces concepts like recursion, pivot selection, and in-place array manipulation.

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 real-world applications, Quick Sort is often used when speed is important and memory usage needs to be efficient. Since it sorts in-place, it doesn’t require extra space for another array, unlike Merge Sort. Learning Quick Sort in Rust also familiarizes beginners with Rust’s ownership rules and slice handling, reinforcing good coding practices while learning a core algorithm.

Program 1: Basic Recursive Quick Sort

This program demonstrates the classic Quick Sort algorithm in Rust using recursion. It selects the last element as the pivot and sorts the array in-place.

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

    if arr.len() <= 1 {
        return;
    }

    let pivot_index = partition(arr);
    let (left, right) = arr.split_at_mut(pivot_index);

    quick_sort(left);
    quick_sort(&mut right[1..]);

}

fn partition(arr: &mut [i32]) -> usize {

    let pivot = arr[arr.len() - 1];
    let mut i = 0;

    for j in 0..arr.len() - 1 {

        if arr[j] <= pivot {
            arr.swap(i, j);
            i += 1;
        }

    }

    arr.swap(i, arr.len() - 1);

    i

}

fn main() {

    let mut numbers = [34, 7, 23, 32, 5, 62];
    println!("Original array: {:?}", numbers);

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

}

This code demonstrates how recursion repeatedly partitions the array around a pivot and sorts each part. Beginners can clearly see how in-place swapping keeps the algorithm memory-efficient.

Program 2: Quick Sort with First Element as Pivot

Here, we select the first element as the pivot. Different pivot strategies can affect performance depending on the input array.

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

    if arr.len() <= 1 {
        return;
    }

    let pivot_index = partition_first(arr);
    let (left, right) = arr.split_at_mut(pivot_index);

    quick_sort_first_pivot(left);
    quick_sort_first_pivot(&mut right[1..]);

}

fn partition_first(arr: &mut [i32]) -> usize {

    let pivot = arr[0];
    let mut i = 1;

    for j in 1..arr.len() {

        if arr[j] < pivot {
            arr.swap(i, j);
            i += 1;
        }

    }

    arr.swap(0, i - 1);
    i - 1

}

fn main() {

    let mut numbers = [10, 80, 30, 90, 40, 50, 70];
    println!("Original array: {:?}", numbers);

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

}

This variant teaches beginners that pivot selection can impact efficiency. It’s also a good introduction to thinking about algorithm optimization.

Program 3: Quick Sort Using Generics

This program shows a generic Quick Sort in Rust that can sort any type implementing the Ord trait, making it flexible for integers, floats, or characters.

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

    if arr.len() <= 1 {
        return;
    }

    let pivot_index = partition_generic(arr);
    let (left, right) = arr.split_at_mut(pivot_index);

    quick_sort_generic(left);
    quick_sort_generic(&mut right[1..]);

}

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

    let pivot_index = arr.len() - 1;
    let pivot = arr[pivot_index].clone(); // pivot is now a value

    let mut i = 0;

    for j in 0..pivot_index {

        if arr[j] <= pivot {
            arr.swap(i, j);
            i += 1;
        }

    }

    arr.swap(i, pivot_index);
    i
}

fn main() {

    let mut int_arr = [5, 2, 9, 1, 5, 6];
    let mut char_arr = ['d', 'a', 'c', 'b'];

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

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

}

Generics allow beginners to write reusable and type-safe sorting functions without rewriting code for different data types.

Program 4: Quick Sort with Debug Prints

This version adds debug statements to visualize the array’s state after each partitioning step.

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

    if arr.len() <= 1 {
        return;
    }

    let pivot_index = partition_debug(arr);
    let (left, right) = arr.split_at_mut(pivot_index);

    quick_sort_debug(left);
    quick_sort_debug(&mut right[1..]);

}

fn partition_debug(arr: &mut [i32]) -> usize {

    let pivot = arr[arr.len() - 1];
    let mut i = 0;

    for j in 0..arr.len() - 1 {

        if arr[j] <= pivot {
            arr.swap(i, j);
            i += 1;
        }

    }

    arr.swap(i, arr.len() - 1);

    println!("Pivot: {}, Array after partition: {:?}", pivot, arr);

    i

}

fn main() {

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

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

}

Debugging helps beginners understand how the array changes with each pivot, making recursion and partitioning more transparent.

Program 5: Quick Sort for Strings

Quick Sort can also handle string arrays. This example sorts words alphabetically.

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

    if arr.len() <= 1 {
        return;
    }

    let pivot_index = partition_strings(arr);
    let (left, right) = arr.split_at_mut(pivot_index);

    quick_sort_strings(left);
    quick_sort_strings(&mut right[1..]);

}

fn partition_strings(arr: &mut [&str]) -> usize {

    let pivot_index = arr.len() - 1;
    let pivot = arr[pivot_index];
    let mut i = 0;

    for j in 0..pivot_index {

        if arr[j] <= pivot {
            arr.swap(i, j);
            i += 1;
        }

    }

    arr.swap(i, pivot_index);

    i

}

fn main() {

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

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

}

Sorting strings demonstrates Quick Sort’s flexibility, showing beginners that the algorithm is not limited to numbers.

Frequently Asked Questions (FAQ)

This section addresses common questions about Quick Sort in Rust.

Q1: Why should beginners learn Quick Sort?
Quick Sort introduces recursion, divide-and-conquer strategies, and in-place array manipulation, all foundational programming concepts.

Q2: Is Quick Sort faster than Bubble Sort?
Yes. Quick Sort has an average time complexity of O(n log n), which is significantly faster for large arrays than Bubble Sort’s O(n²).

Q3: Can Quick Sort work with strings in Rust?
Yes, as long as the array elements implement the Ord trait.

Q4: What is the main idea behind Quick Sort?
Select a pivot, partition the array around it, and recursively sort the subarrays.

Q5: When is Quick Sort most efficient?
Quick Sort performs best on large, randomly ordered arrays and is memory-efficient due to in-place sorting.

Conclusion

Quick Sort is an essential algorithm for beginners learning Rust, as it combines recursion, pivot-based partitioning, and efficient in-place sorting. By exploring multiple implementations—including generic types, strings, and debug versions—learners can understand both the mechanics and flexibility of the algorithm. Practicing Quick Sort helps build a solid foundation for understanding other advanced sorting techniques, preparing beginners for more complex programming challenges. With consistent practice, Quick Sort becomes a powerful tool in any Rust programmer’s toolkit.

Scroll to Top