Heap (Priority Queue)
Heap is a specialized complete binary tree data structure that satisfies the heap property, designed for efficient retrieval of the maximum or minimum element. It is commonly used to implement a priority queue—a data structure where elements are processed based on their priority (not insertion order). Heaps are foundational for algorithms like Heap Sort, Dijkstra’s, and Prim’s MST.
There are two primary types of heaps:
- Max-Heap: The value of each parent node is greater than or equal to the values of its children. The root node is the maximum element in the heap.
- Min-Heap: The value of each parent node is less than or equal to the values of its children. The root node is the minimum element in the heap.
Core Concepts & Properties
1. Complete Binary Tree
A complete binary tree is a tree where all levels are fully filled except possibly the last level, which is filled from left to right. This property allows heaps to be efficiently stored in arrays (no wasted space), with parent-child relationships determined by indices:
- For a node at index
i(0-based array):- Left child:
2i + 1 - Right child:
2i + 2 - Parent:
(i - 1) // 2(integer division)
- Left child:
2. Heap Property
- Max-Heap:
heap[parent(i)] ≥ heap[left(i)]andheap[parent(i)] ≥ heap[right(i)] - Min-Heap:
heap[parent(i)] ≤ heap[left(i)]andheap[parent(i)] ≤ heap[right(i)]
Example Max-Heap (Array Representation)
plaintext
Heap Tree Structure: Array Representation (0-based):
100 (root) [100, 80, 90, 70, 60, 40, 50, 30]
/ \
80 90
/ \ / \
70 60 40 50
/
30
Parent-Child Indices:
- Node 100 (i=0) → Left (i=1:80), Right (i=2:90)
- Node 80 (i=1) → Left (i=3:70), Right (i=4:60)
- Node 90 (i=2) → Left (i=5:40), Right (i=6:50)
- Node 70 (i=3) → Left (i=7:30), Right (i=8: None)
Key Operations
Heaps support 4 core operations, all optimized to maintain the heap property:
- Insert: Add a new element to the heap (O(log n)).
- Extract Max/Min: Remove and return the root element (maximum in Max-Heap, minimum in Min-Heap) (O(log n)).
- Heapify: Convert an unordered array into a heap (O(n)).
- Peek: Return the root element without removing it (O(1)).
Critical Sub-Operations
To maintain the heap property during insert/extract, two helper operations are used:
- Bubble Up (Heapify Up): Move a node up the tree to its correct position (used in
insert). - Bubble Down (Heapify Down): Move a node down the tree to its correct position (used in
extractandheapify).
Heap Implementation (Python)
We’ll implement a Max-Heap (easily modifiable to Min-Heap by reversing the comparison logic). The implementation uses a list to store the heap and includes all core operations.
Full Implementation
python
运行
class MaxHeap:
def __init__(self):
self.heap = [] # Array to store the heap
# -------------------------- Helper Methods --------------------------
def _parent(self, index):
"""Return the index of the parent node."""
return (index - 1) // 2
def _left_child(self, index):
"""Return the index of the left child node."""
return 2 * index + 1
def _right_child(self, index):
"""Return the index of the right child node."""
return 2 * index + 2
def _swap(self, i, j):
"""Swap elements at indices i and j."""
self.heap[i], self.heap[j] = self.heap[j], self.heap[i]
# -------------------------- Bubble Up (Heapify Up) --------------------------
def _bubble_up(self, index):
"""Move the node at 'index' up to its correct position to maintain Max-Heap property."""
parent_idx = self._parent(index)
# While node is not root and parent value < current node value (violates Max-Heap)
while index > 0 and self.heap[parent_idx] < self.heap[index]:
self._swap(parent_idx, index)
index = parent_idx
parent_idx = self._parent(index)
# -------------------------- Bubble Down (Heapify Down) --------------------------
def _bubble_down(self, index):
"""Move the node at 'index' down to its correct position to maintain Max-Heap property."""
n = len(self.heap)
while True:
left_idx = self._left_child(index)
right_idx = self._right_child(index)
largest_idx = index # Assume current node is the largest
# Check if left child exists and is larger than current largest
if left_idx < n and self.heap[left_idx] > self.heap[largest_idx]:
largest_idx = left_idx
# Check if right child exists and is larger than current largest
if right_idx < n and self.heap[right_idx] > self.heap[largest_idx]:
largest_idx = right_idx
# If current node is already the largest, heap property is restored
if largest_idx == index:
break
# Swap current node with the largest child and continue bubbling down
self._swap(index, largest_idx)
index = largest_idx
# -------------------------- Core Operations --------------------------
def insert(self, value):
"""Insert a new value into the heap."""
# Add value to the end of the heap (maintains complete binary tree property)
self.heap.append(value)
# Bubble up to restore Max-Heap property
self._bubble_up(len(self.heap) - 1)
def extract_max(self):
"""Remove and return the maximum value (root) from the heap. Return None if heap is empty."""
if not self.heap:
return None
n = len(self.heap)
# Swap root (max) with the last element (maintains complete binary tree)
self._swap(0, n - 1)
# Remove the max value from the end of the heap
max_value = self.heap.pop()
# Bubble down the new root to restore Max-Heap property
self._bubble_down(0)
return max_value
def peek_max(self):
"""Return the maximum value (root) without removing it. Return None if heap is empty."""
return self.heap[0] if self.heap else None
def heapify(self, arr):
"""Convert an unordered array into a Max-Heap (in-place)."""
self.heap = arr.copy()
n = len(self.heap)
# Start heapifying from the last non-leaf node (all leaf nodes are already heaps)
# Last non-leaf node index: (n // 2) - 1
for i in range(n // 2 - 1, -1, -1):
self._bubble_down(i)
def is_empty(self):
"""Check if the heap is empty."""
return len(self.heap) == 0
def size(self):
"""Return the number of elements in the heap."""
return len(self.heap)
# Test the MaxHeap implementation
if __name__ == "__main__":
# Initialize MaxHeap
max_heap = MaxHeap()
# Insert elements
values = [30, 70, 80, 100, 60, 40, 90, 50]
for val in values:
max_heap.insert(val)
print("Heap after insertions:", max_heap.heap) # Output: [100, 80, 90, 70, 60, 40, 30, 50]
# Peek max
print("Peek max:", max_heap.peek_max()) # Output: 100
# Extract max
print("\nExtracting max values:")
while not max_heap.is_empty():
print(max_heap.extract_max(), end=" ") # Output: 100 90 80 70 60 50 40 30
print()
# Heapify an unordered array
unordered_arr = [5, 3, 8, 1, 2, 9, 4]
max_heap.heapify(unordered_arr)
print("\nHeap after heapifying [5,3,8,1,2,9,4]:", max_heap.heap) # Output: [9, 3, 8, 1, 2, 5, 4]
Min-Heap Modification
To convert the Max-Heap to a Min-Heap, reverse the comparison logic in _bubble_up and _bubble_down:
- In
_bubble_up: Changeself.heap[parent_idx] < self.heap[index]toself.heap[parent_idx] > self.heap[index]. - In
_bubble_down: Changeself.heap[left_idx] > self.heap[largest_idx]toself.heap[left_idx] < self.heap[smallest_idx](and similarly for the right child).
Time and Space Complexity
| Operation | Time Complexity | Explanation |
|---|---|---|
| Insert | O(log n) | Bubble up traverses the height of the heap (height of complete binary tree = log n). |
| Extract Max/Min | O(log n) | Bubble down traverses the height of the heap. |
| Heapify | O(n) | Contrary to intuition—heapifying from the last non-leaf node takes linear time (mathematically proven). |
| Peek | O(1) | Direct access to the root element (index 0). |
| Size/Is Empty | O(1) | Directly check the length of the heap array. |
| Space Complexity | O(n) | Stores n elements in the heap array (no extra space for tree structure—uses array indices). |
Pros and Cons of Heaps
Pros
- Efficient Extremum Retrieval: Extracting the max/min element is O(log n) (far faster than arrays (O(n)) or unsorted lists (O(n))).
- Priority Queue Implementation: The de facto standard for priority queues (critical for Dijkstra’s, Prim’s, and Huffman Coding).
- In-Place Heap Sort: Heapify enables an efficient O(n log n) sorting algorithm with O(1) auxiliary space.
- Complete Binary Tree Efficiency: Stored as an array with no wasted space (unlike linked trees).
Cons
- No Random Access: Cannot efficiently access arbitrary elements (only the root is accessible in O(1) time).
- No Ordered Traversal: Heaps do not maintain elements in sorted order (only the heap property)—sorted traversal requires extracting elements one by one (O(n log n)).
- Slow for Non-Extremum Operations: Finding or deleting an arbitrary element is O(n) (must scan the entire array).
- Fixed Heap Type: A Max-Heap cannot efficiently retrieve the minimum element (and vice versa) without extra logic.
Real-World Applications of Heaps
- Priority Queues: Task scheduling (e.g., operating systems prioritizing high-priority processes), job queues (e.g., print spoolers), and event-driven simulations (e.g., processing events in time order).
- Sorting: Heap Sort (O(n log n) time, O(1) space) — useful for memory-constrained environments.
- Graph Algorithms: Dijkstra’s shortest path algorithm (uses a min-heap to track the next node with the smallest tentative distance) and Prim’s MST algorithm (uses a min-heap to track the next edge with the smallest weight).
- Data Streaming: Finding the k largest/smallest elements in a stream (e.g., top 10 trending topics on Twitter) using a min-heap/max-heap of size k (O(n log k) time).
- Huffman Coding: Compression algorithms use heaps to build optimal prefix codes.
- Median Maintenance: Maintaining the median of a dynamic dataset using two heaps (max-heap for lower half, min-heap for upper half).
Heap vs. Other Data Structures (Key Differences)
| Feature | Heap | Array (Sorted) | Hash Table | Binary Search Tree (Balanced) |
|---|---|---|---|---|
| Extract Max/Min | O(log n) | O(1) (last/first element) | O(n) (must scan all elements) | O(log n) (max: rightmost node) |
| Insert | O(log n) | O(n) (shift elements) | O(1) (average case) | O(log n) |
| Search Arbitrary Element | O(n) | O(log n) (binary search) | O(1) (average case) | O(log n) |
| Sorted Traversal | O(n log n) (extract all) | O(n) (direct traversal) | O(n log n) (sort first) | O(n) (in-order traversal) |
Summary
Weaknesses: No random access, no sorted traversal, slow arbitrary element operations.
A Heap is a complete binary tree with the max/min-heap property, stored as an array for efficiency.
Core operations: Insert (O(log n)), Extract Max/Min (O(log n)), Heapify (O(n)), Peek (O(1)).
Key use case: Implementing priority queues for algorithms and scheduling.
Strengths: Fast extremum retrieval, efficient priority-based processing, low space overhead.
- High-Performance Waterproof Solar Connectors
- Durable IP68 Waterproof Solar Connectors for Outdoor Use
- High-Quality Tinned Copper Material for Durability
- High-Quality Tinned Copper Material for Long Service Life
- Y Branch Parallel Solar Connector for Enhanced Power
- 10AWG Tinned Copper Solar Battery Cables
- NEMA 5-15P to Powercon Extension Cable Overview
- Dual Port USB 3.0 Adapter for Optimal Speed
- 4-Pin XLR Connector: Reliable Audio Transmission
- 4mm Banana to 2mm Pin Connector: Your Audio Solution
- 12GB/s Mini SAS to U.2 NVMe Cable for Fast Data Transfer
- CAB-STK-E Stacking Cable: 40Gbps Performance
- High-Performance CAB-STK-E Stacking Cable Explained
- Best 10M OS2 LC to LC Fiber Patch Cable for Data Centers
- Mini SAS HD Cable: Boost Data Transfer at 12 Gbps
- Multi Rate SFP+: Enhance Your Network Speed
- Best 6.35mm to MIDI Din Cable for Clear Sound
- 15 Pin SATA Power Splitter: Solutions for Your Device Needs
- 9-Pin S-Video Cable: Enhance Your Viewing Experience
- USB 9-Pin to Standard USB 2.0 Adapter: Easy Connection
- 3 Pin to 4 Pin Fan Adapter: Optimize Your PC Cooling
- S-Video to RCA Cable: High-Definition Connections Made Easy
- 6.35mm TS Extension Cable: High-Quality Sound Solution
- BlackBerry Curve 9360: Key Features and Specs






















Leave a comment