Priority Queue Introduction and Concept in DSA Rust - Time & Space Complexity
We want to understand how the time needed to use a priority queue changes as we add or remove items.
How does the cost grow when the queue gets bigger?
Analyze the time complexity of the following code snippet.
struct PriorityQueue {
data: Vec<i32>,
}
impl PriorityQueue {
fn push(&mut self, value: i32) {
self.data.push(value);
self.data.sort_unstable_by(|a, b| b.cmp(a));
}
fn pop(&mut self) -> Option<i32> {
self.data.pop()
}
}
This code adds values to a list and keeps it sorted so the biggest value is always first for easy removal.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Sorting the list after each insertion.
- How many times: Sorting happens every time we add a new value.
Sorting takes longer as the list grows because it compares more items.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 50 comparisons |
| 100 | About 700 comparisons |
| 1000 | About 10,000 comparisons |
Pattern observation: The work grows faster than the number of items, roughly like n times log n.
Time Complexity: O(n log n)
This means adding one item takes longer as the list grows, but not as fast as checking every pair.
[X] Wrong: "Adding an item is always fast because we just put it at the end."
[OK] Correct: We must sort after adding, which takes more time as the list grows.
Knowing how priority queues work and their time costs helps you explain choices clearly in interviews.
"What if we used a binary heap instead of sorting the list every time? How would the time complexity change?"
Practice
Priority Queue compared to a regular queue?Solution
Step 1: Understand queue behavior
A regular queue removes elements in the order they were added (FIFO).Step 2: Understand priority queue behavior
A priority queue removes elements based on their priority, not just insertion order.Final Answer:
Elements are dequeued based on priority, not just order of insertion -> Option CQuick Check:
Priority Queue = Priority-based removal [OK]
- Confusing priority queue with FIFO queue
- Thinking priority queue sorts elements permanently
- Assuming priority queue disallows duplicates
std::collections::BinaryHeap?Solution
Step 1: Recall Rust BinaryHeap creation
The standard way to create a max-heap priority queue is usingBinaryHeap::new().Step 2: Check other options
with_capacity(10i32)type mismatch (usize expected);default(10)invalid arguments;min_heap()does not exist.Final Answer:
let mut pq = std::collections::BinaryHeap::new(); -> Option DQuick Check:
BinaryHeap::new() creates max-heap [OK]
- Using with_capacity with i32 instead of usize
- Passing arguments to default()
- Using non-existent min_heap() method
use std::collections::BinaryHeap;
fn main() {
let mut pq = BinaryHeap::new();
pq.push(10);
pq.push(5);
pq.push(20);
while let Some(val) = pq.pop() {
print!("{} ", val);
}
}Solution
Step 1: Understand BinaryHeap behavior
Rust's BinaryHeap is a max-heap by default, so pop() returns the largest element first.Step 2: Trace the pop order
Inserted values: 10, 5, 20. Popping returns 20, then 10, then 5.Final Answer:
20 10 5 -> Option AQuick Check:
Max-heap pop order = descending [OK]
- Assuming pop returns elements in insertion order
- Thinking BinaryHeap is min-heap by default
- Mixing up push and pop order
use std::collections::BinaryHeap;
fn main() {
let mut pq = BinaryHeap::new();
pq.push(3);
pq.push(1);
pq.push(2);
while let Some(val) = pq.pop() {
println!("{}", val);
}
}Solution
Step 1: Check BinaryHeap default behavior
Rust's BinaryHeap is a max-heap by default, so it does not create a min-heap without extra work.Step 2: Verify code correctness
push() and pop() methods exist and println! is correct; the issue is the heap type.Final Answer:
BinaryHeap does not support min-heap by default -> Option AQuick Check:
BinaryHeap default = max-heap, no min-heap [OK]
- Assuming BinaryHeap is min-heap by default
- Thinking push() or pop() are missing
- Misreading println! syntax
use std::collections::BinaryHeap;
struct Task {
priority: i32,
name: String,
}
fn main() {
let mut pq = BinaryHeap::new();
pq.push(Task { priority: 2, name: String::from("Clean") });
pq.push(Task { priority: 5, name: String::from("Cook") });
pq.push(Task { priority: 1, name: String::from("Shop") });
while let Some(task) = pq.pop() {
println!("{}", task.name);
}
}What must you do to make this code work as intended?
Solution
Step 1: Understand BinaryHeap requirements
BinaryHeap requires elements to implementOrdandEqto compare and order them.Step 2: Check code for ordering
Task struct has no ordering traits implemented, so BinaryHeap cannot order tasks by priority.Step 3: Correct approach
ImplementOrdandEqfor Task to order by priority, so highest priority pops first.Final Answer:
Implement Ord and Eq traits for Task to order by priority -> Option BQuick Check:
BinaryHeap needs Ord/Eq for custom types [OK]
- Using Vec instead of priority queue
- Changing data type without ordering
- Using peek() instead of pop() to remove elements
Ready to prove it?
Pass the test and this pattern moves unknown
