Heap Construction and Extraction
BinaryHeap<T> supports $O(n)$ bulk construction from an existing vector or array (BinaryHeap::from(vec)) and zero-reallocation conversions back into a Vec<T>—either in arbitrary heap-array order ($O(1)$ via .into_vec()) or in ascending sorted order ($O(n \log n)$ via .into_sorted_vec()).
Bulk Construction: $O(n)$ From<Vec<T>> vs. $O(n \log n)$ Repeated push()
Pushing $n$ elements one at a time into an empty BinaryHeap takes $O(n \log n)$ worst-case time. By contrast, constructing a BinaryHeap in bulk via BinaryHeap::from(vec) or .collect::<BinaryHeap<T>>() reuses the Vec<T> allocation in place and runs Floyd's bottom-up heapify algorithm (rebuild), which sifts down only the non-leaf nodes (0..len / 2) in $O(n)$ linear time:
Floyd's Bottom-Up Heapify on [20, 80, 50, 90, 60] (n = 5):
- Leaves at indices 2..5 ([50, 90, 60]) are already valid 1-element heaps
- Sift down index 1 (80 vs children 90, 60) -> swaps 80 and 90
- Sift down index 0 (20 vs children 90, 50) -> swaps 20 -> 90 -> 80
Total work across all levels: sum_{h=0}^{log n} (n / 2^{h+1}) * O(h) = O(n)!
use std::collections::BinaryHeap;
fn main() {
let raw_vec = vec![20, 80, 50, 90, 60];
let vec_ptr = raw_vec.as_ptr();
// O(n) in-place heap construction reusing `raw_vec`'s heap buffer:
let heap = BinaryHeap::from(raw_vec);
println!("Max element: {:?}", heap.peek());
println!(
"Reused allocation in place: {}",
heap.as_slice().as_ptr() == vec_ptr
);
}
Max element: Some(&90)
Reused allocation in place: true
Extracting Elements from a BinaryHeap<T>
| Method | Return Type | Time Complexity | Element Order |
|---|---|---|---|
heap.into_vec() (or Vec::from(heap)) |
Vec<T> |
$O(1)$ (zero copy) | Arbitrary heap-array order |
heap.into_sorted_vec() |
Vec<T> |
$O(n \log n)$ (in-place heapsort) | Ascending sorted order (v[0] is smallest) |
while let Some(x) = heap.pop() |
T (one by one) |
$O(k \log n)$ for $k$ pops | Descending sorted order (largest first) |
heap.drain() |
Drain<'_, T> |
$O(n)$ | Arbitrary heap-array order (retains capacity) |
use std::collections::BinaryHeap;
fn main() {
let heap = BinaryHeap::from([40, 10, 90, 30, 70]);
// Consumes the heap and performs an in-place heapsort into an ascending Vec<i32>:
let sorted_asc: Vec<i32> = heap.into_sorted_vec();
println!("into_sorted_vec (ascending): {sorted_asc:?}");
}
into_sorted_vec (ascending): [10, 30, 40, 70, 90]
Merging Two Heaps with append(&mut other)
Calling heap_a.append(&mut heap_b) moves all elements from heap_b into heap_a's backing Vec<T> and rebuilds the heap invariant in $O(|a| + |b|)$ (or $O(|b| \log(|a| + |b|))$ when $|b| \ll |a|$), leaving heap_b empty.