Consider a priority queue where you need to insert elements and extract the minimum element repeatedly. Why is a heap data structure preferred over a sorted array for this use case?
Think about how much work is needed to keep the data sorted after inserting a new element.
A heap maintains a partial order that allows insertion and extraction of the minimum element in O(log n) time. A sorted array requires shifting elements to insert a new item, which takes O(n) time. This makes heaps more efficient for dynamic priority queues.
What is the state of the min-heap array after inserting the elements 5, 3, 8, 1 in that order?
package main import ( "container/heap" "fmt" ) type IntHeap []int func (h IntHeap) Len() int { return len(h) } func (h IntHeap) Less(i, j int) bool { return h[i] < h[j] } func (h IntHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] } func (h *IntHeap) Push(x interface{}) { *h = append(*h, x.(int)) } func (h *IntHeap) Pop() interface{} { old := *h n := len(old) x := old[n-1] *h = old[0 : n-1] return x } func main() { h := &IntHeap{} heap.Init(h) heap.Push(h, 5) heap.Push(h, 3) heap.Push(h, 8) heap.Push(h, 1) fmt.Println(*h) }
Remember that a min-heap keeps the smallest element at the root and maintains the heap property.
After inserting 5, 3, 8, 1 into a min-heap, the internal array representation is [1 3 8 5]. The smallest element 1 is at the root (index 0), and the heap property is maintained.
Given a sorted array and a min-heap both containing the same elements, why does extracting the minimum element repeatedly take longer on the sorted array?
Think about what happens to the array elements after removing the first element.
In a sorted array, removing the first element requires shifting all remaining elements left by one, which takes O(n) time. In a heap, extracting the minimum element involves swapping and heapifying, which takes O(log n) time, making it more efficient for repeated extractions.
What is the output after inserting 4, 7, 2 into an empty min-heap and then extracting the minimum element once?
package main import ( "container/heap" "fmt" ) type IntHeap []int func (h IntHeap) Len() int { return len(h) } func (h IntHeap) Less(i, j int) bool { return h[i] < h[j] } func (h IntHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] } func (h *IntHeap) Push(x interface{}) { *h = append(*h, x.(int)) } func (h *IntHeap) Pop() interface{} { old := *h n := len(old) x := old[n-1] *h = old[0 : n-1] return x } func main() { h := &IntHeap{} heap.Init(h) heap.Push(h, 4) heap.Push(h, 7) heap.Push(h, 2) min := heap.Pop(h).(int) fmt.Println(min) fmt.Println(*h) }
Recall that heap.Pop removes the smallest element and then reorders the heap.
The minimum element 2 is extracted first. The heap then reorders to maintain the heap property, resulting in [4 7].
Explain why a sorted array is inefficient for a priority queue that requires frequent insertions and extractions of the minimum element.
Think about the cost of maintaining sorted order after each insertion and extraction.
Sorted arrays keep elements in order, so inserting a new element requires shifting elements to make space, which takes O(n) time. Similarly, extracting the minimum (usually the first element) requires shifting all remaining elements left, also O(n). This double cost makes sorted arrays inefficient for dynamic priority queues.