Sorting Vectors
Through deref coercion to [T], Vec<T> provides two complete families of $O(n \log n)$ sorting methods: stable sorts (.sort(), .sort_by(), .sort_by_key(), .sort_by_cached_key()) and unstable sorts (.sort_unstable(), .sort_unstable_by(), .sort_unstable_by_key()).
Stable vs. Unstable Sorting Methods
| Method | Stable? (Preserves Order of Equal Elements) | Auxiliary Heap Allocation | Required Bounds |
|---|---|---|---|
v.sort() |
Yes (driftsort) |
Up to $O(n)$ scratch space | T: Ord |
v.sort_by(cmp) |
Yes | Up to $O(n)$ scratch space | cmp: FnMut(&T, &T) -> Ordering |
v.sort_by_key(k) |
Yes | Up to $O(n)$ scratch space | k: FnMut(&T) -> K, K: Ord |
v.sort_by_cached_key(k) |
Yes | $O(n)$ key cache + scratch space | Computes k(&elem) once per element |
v.sort_unstable() |
No (ipnsort) |
Zero (0 bytes, in-place) |
T: Ord |
v.sort_unstable_by(cmp) |
No | Zero (0 bytes, in-place) |
cmp: FnMut(&T, &T) -> Ordering |
v.sort_unstable_by_key(k) |
No | Zero (0 bytes, in-place) |
k: FnMut(&T) -> K, K: Ord |
For primitive types (i32, u64, char) where equal values are indistinguishable, v.sort_unstable() is strictly faster and uses zero extra heap memory.
Sorting Ascending, Descending, by Key, and Multi-Field
use std::cmp::Reverse;
#[derive(Debug)]
struct Task {
priority: u8,
name: &'static str,
}
fn main() {
// 1. Fast in-place unstable sort on primitives:
let mut nums = vec![42, 7, 19, 7, 3];
nums.sort_unstable();
println!("Ascending: {nums:?}");
// 2. Descending sort using `std::cmp::Reverse`:
nums.sort_unstable_by_key(|&n| Reverse(n));
println!("Descending: {nums:?}");
// 3. Stable sort by key (preserves original relative order of ties):
let mut tasks = vec![
Task { priority: 2, name: "backup" },
Task { priority: 1, name: "auth" },
Task { priority: 2, name: "cleanup" },
];
tasks.sort_by_key(|t| t.priority);
println!("Tasks by priority: {tasks:?}");
}
Ascending: [3, 7, 7, 19, 42]
Descending: [42, 19, 7, 7, 3]
Tasks by priority: [Task { priority: 1, name: "auth" }, Task { priority: 2, name: "backup" }, Task { priority: 2, name: "cleanup" }]
Sorting Floating-Point Vectors (f64::total_cmp)
Because f32 and f64 implement PartialOrd rather than Ord (due to NaN), calling .sort() directly on a Vec<f64> does not compile. Pass f64::total_cmp (or f32::total_cmp) to .sort_by() or .sort_unstable_by():
fn main() {
let mut measurements = vec![3.5_f64, -1.2, 0.0, 9.8, 2.1];
measurements.sort_unstable_by(f64::total_cmp);
println!("Sorted floats: {measurements:?}");
}
Sorted floats: [-1.2, 0.0, 2.1, 3.5, 9.8]
Partial Sorting in $O(n)$ Time (select_nth_unstable)
If you only need the $k$-th smallest element or the top $k$ smallest elements without sorting the entire vector, v.select_nth_unstable(k) (Quickselect / Introselect) partitions the slice in $O(n)$ average time so that v[k] is in its final sorted position, all elements in v[..k] are $\le v[k]$, and all elements in v[k + 1..] are $\ge v[k]$.