12. Heaps (Đống)
🎯 Mục tiêu học tập
- Hiểu cấu trúc heap và heap property
- Cài đặt min heap và max heap
- Thuật toán heapify và heap sort
- Ứng dụng heap vào priority queue
📚 Lý thuyết
Heap là gì?
Định nghĩa: Complete binary tree thỏa mãn heap property.
Heap Property:
- Max Heap: Parent ≥ Children (root là max)
- Min Heap: Parent ≤ Children (root là min)
Đặc điểm:
- Complete binary tree (fill từ trái sang phải)
- Height = O(log n)
- Thường implement bằng array
🏗️ Array Representation
// Với node ở index i:
// Left child: 2*i + 1
// Right child: 2*i + 2
// Parent: (i-1)/2
class MinHeap {
private int[] heap;
private int size;
private int capacity;
}
🔧 Basic Operations
1. Insert (O(log n))
void insert(int value) {
// 1. Thêm vào cuối array
heap[size] = value;
size++;
// 2. Heapify up
heapifyUp(size - 1);
}
void heapifyUp(int index) {
while (index > 0) {
int parent = (index - 1) / 2;
if (heap[index] >= heap[parent]) break;
swap(index, parent);
index = parent;
}
}
2. Extract Min/Max (O(log n))
int extractMin() {
// 1. Lưu root
int min = heap[0];
// 2. Move last element to root
heap[0] = heap[size - 1];
size--;
// 3. Heapify down
heapifyDown(0);
return min;
}
void heapifyDown(int index) {
while (true) {
int smallest = index;
int left = 2 * index + 1;
int right = 2 * index + 2;
if (left < size && heap[left] < heap[smallest])
smallest = left;
if (right < size && heap[right] < heap[smallest])
smallest = right;
if (smallest == index) break;
swap(index, smallest);
index = smallest;
}
}
3. Peek (O(1))
int peek() {
if (size == 0) throw new RuntimeException("Heap is empty");
return heap[0];
}
4. Build Heap (O(n))
void buildHeap(int[] array) {
heap = Arrays.copyOf(array, array.length);
size = array.length;
// Heapify từ last internal node về root
for (int i = (size - 2) / 2; i >= 0; i--) {
heapifyDown(i);
}
}
🎯 Applications
1. Priority Queue
PriorityQueue<Integer> pq = new PriorityQueue<>(); // Min heap
PriorityQueue<Integer> maxPq = new PriorityQueue<>(Collections.reverseOrder());
2. Heap Sort
void heapSort(int[] arr) {
// 1. Build max heap
buildMaxHeap(arr);
// 2. Extract max repeatedly
for (int i = arr.length - 1; i > 0; i--) {
swap(0, i); // Move max to end
heapifyDown(0, i); // Heapify reduced heap
}
}
3. K-way Merge
// Merge k sorted arrays
PriorityQueue<Element> pq = new PriorityQueue<>();
// Add first element from each array
// Keep extracting min and adding next element
4. Top K Problems
// Find K largest elements
PriorityQueue<Integer> minHeap = new PriorityQueue<>();
for (int num : nums) {
minHeap.offer(num);
if (minHeap.size() > k) {
minHeap.poll();
}
}
🔍 Types of Heaps
1. Binary Heap
- Standard heap với 2 children per node
- Array implementation
2. d-ary Heap
- d children per node
- Reduce height nhưng increase heapify cost
3. Fibonacci Heap
- Advanced heap với better amortized complexity
- Decrease key: O(1) amortized
4. Binomial Heap
- Forest of binomial trees
- Union operation: O(log n)
📊 Complexity Analysis
| Operation | Binary Heap | Fibonacci Heap |
|---|---|---|
| Insert | O(log n) | O(1) amortized |
| Extract Min | O(log n) | O(log n) amortized |
| Decrease Key | O(log n) | O(1) amortized |
| Union | O(n) | O(1) |
| Find Min | O(1) | O(1) |
📋 Bài tập thực hành
Cơ bản:
- Implement min heap và max heap
- Heap sort implementation
- Kth largest element in array
- Merge k sorted lists
Trung bình:
- Top K frequent elements
- Find median from data stream
- Ugly Number II
- Meeting Rooms II
Nâng cao:
- Sliding window median
- Smallest range covering K lists
- IPO problem
- Minimum cost to hire K workers
💡 Optimization Tips
1. Space Optimization
// In-place heap sort
// Use existing array as heap
2. Custom Comparators
PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> a[1] - b[1]);
3. Lazy Deletion
// Mark as deleted instead of actually removing
// Clean up during next operation
⚠️ Common Mistakes
1. Index Calculation
// Wrong: parent = i/2 (for 1-indexed)
// Right: parent = (i-1)/2 (for 0-indexed)
2. Build Heap
// Inefficient: Insert one by one O(n log n)
// Efficient: Bottom-up heapify O(n)
3. Heap vs Priority Queue
// Java PriorityQueue là min heap by default
// Muốn max heap: PriorityQueue<>(Collections.reverseOrder())
🚀 Chuẩn bị code
mkdir 12-heaps
# Files:
# - MinHeap.java
# - MaxHeap.java
# - HeapSort.java
# - PriorityQueueApplications.java
# - HeapProblems.java