Heaps and priority queues — SplMinHeap, SplMaxHeap
Advanced5 min read·eng-07-005
compare
Concept
Heap: A complete binary tree that satisfies the heap property:
- Min-heap: Parent ≤ children. The root is always the minimum element.
- Max-heap: Parent ≥ children. The root is always the maximum element.
Key operations (all O(log n) except peek):
insert: Add to the bottom, "bubble up" (sift up) to restore the heap property.extract(pop min/max): Remove root, put the last element at root, "bubble down" (sift down).peek(top):O(1)— just read the root.heapify: Build a heap from an array —O(n)(more efficient than n inserts).
Why heaps: When you need the min or max element repeatedly, but items are added dynamically. Examples: Dijkstra's algorithm, A* pathfinding, Huffman encoding, top-K problems.
Priority Queue: A data structure that always gives you the highest-priority element first. A heap is the typical implementation.
PHP SPL:
SplMinHeap: Extract the minimum element.SplMaxHeap: Extract the maximum element.SplPriorityQueue: Priority queue where you specify the priority separately.- All implement
SplHeap.
Array representation: A heap is typically stored as an array. For node at index i:
- Left child:
2*i + 1 - Right child:
2*i + 2 - Parent:
floor((i-1) / 2)
Top-K pattern: Find the K largest (or smallest) elements from N elements. Maintain a min-heap of size K. If new element > heap minimum, pop min and push new element. Final heap contains top K. O(n log k) — much better than O(n log n) sort.
Code Example
php
<?php
// SplMinHeap — always extracts the minimum
$minHeap = new \SplMinHeap();
$minHeap->insert(15);
$minHeap->insert(3);
$minHeap->insert(8);
$minHeap->insert(1);
echo $minHeap->extract(); // 1 (minimum)
echo $minHeap->extract(); // 3
echo $minHeap->top(); // 8 (peek without removal)
// SplMaxHeap — always extracts the maximum
$maxHeap = new \SplMaxHeap();
foreach ([5, 10, 2, 8, 1] as $val) { $maxHeap->insert($val); }
echo $maxHeap->extract(); // 10
// SplPriorityQueue — items with explicit priority (higher number = higher priority)
$taskQueue = new \SplPriorityQueue();
$taskQueue->setExtractFlags(\SplPriorityQueue::EXTR_BOTH); // get data AND priority
$taskQueue->insert(['action' => 'send_email'], priority: 1);
$taskQueue->insert(['action' => 'process_payment'], priority: 10); // highest priority
$taskQueue->insert(['action' => 'update_cache'], priority: 5);
while (!$taskQueue->isEmpty()) {
$item = $taskQueue->extract();
echo "{$item['data']['action']} (priority: {$item['priority']})\n";
}
// Output: process_payment (10), update_cache (5), send_email (1)
// Top-K elements — find K largest using a min-heap of size K
function topK(array $nums, int $k): array
{
$heap = new \SplMinHeap();
foreach ($nums as $num) {
$heap->insert($num);
if ($heap->count() > $k) {
$heap->extract(); // remove the minimum — keep only K largest
}
}
$result = [];
while (!$heap->isEmpty()) { $result[] = $heap->extract(); }
return array_reverse($result); // largest first
}
$top3 = topK([3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5], 3);
print_r($top3); // [9, 6, 5]
// Dijkstra's shortest path uses a min-heap (conceptual):
// - Store (distance, node) pairs
// - Always process the node with the smallest known distance next
// PHP implementation would use SplMinHeap with custom comparison