Sorting
Quick Sort (Lomuto)
Choose the last item as a pivot, partition smaller values to its left, then recurse on the two sides.
Algorithm
The checked-in replay follows the same small input and final output across all 21 DSA books, so this Rust DSA implementation can be compared directly with the other languages.
pivot
The final element is moved to the boundary between smaller and larger values.
partition
One scan rearranges the current range before the recursive calls.
Visual walkthrough
Basic Implementation
basic.rs
fn partition(arr: &mut [i32], low: usize, high: usize) -> usize {
let pivot = arr[high];
let mut i = low;
for j in low..high {
if arr[j] <= pivot {
arr.swap(i, j);
i += 1;
}
}
arr.swap(i, high);
i
}
fn quick_sort(arr: &mut [i32], low: usize, high: usize) {
if low < high {
let pivot_index = partition(arr, low, high);
if pivot_index > 0 {
quick_sort(arr, low, pivot_index - 1);
}
quick_sort(arr, pivot_index + 1, high);
}
}
fn main() {
let mut arr = [4, 1, 5, 2, 3];
let last = arr.len() - 1;
quick_sort(&mut arr, 0, last);
println!("{:?}", arr);
}
Complexity
- Time: O(n^2) worst, O(n log n) average
- Space: O(log n) average call stack
- Stable: no
Implementation notes
- The checked source uses a fixed mutable array,
let mut arr = [4, 1, 5, 2, 3], and passes it as&mut [i32]; it does not allocate aVec. partition(arr: &mut [i32], low: usize, high: usize) -> usizereceives the mutable slice plus bounds, choosespivot = arr[high], and returns the final pivot index.quick_sort(arr: &mut [i32], low: usize, high: usize)mutates in place and returns(). It recurses only whenlow < high.- The source keeps
ias the next left-side write slot and scansfor j in low..high. Onarr[j] <= pivot,arr.swap(i, j)moves that value left and then incrementsi. - After the scan,
arr.swap(i, high)places the pivot. The recursive left call is guarded byif pivot_index > 0sopivot_index - 1cannot underflow as ausize. - The trace records the first partition around pivot
3: keep4, swap1left, keep5, swap2left, then swap the pivot into index2, yielding[1, 2, 3, 4, 5]. Itsilabels the left boundary, while the Rust variable holds the next write slot. - Recursive calls on
[1, 2]and[4, 5]are summarized in the trace. The finalprintln!("{:?}", arr)uses debug formatting and prints[1, 2, 3, 4, 5].