Implement a binary max-heap using an array, supporting operations:
- Insert an element
- Get maximum element
- Extract (remove + return) maximum
- Increase the key at some index
- Delete an element at a given index
This is very similar to the binary min-heap — only the comparisons flip sign.
A max-heap satisfies:
For every node
i:arr[i] >= arr[left(i)]andarr[i] >= arr[right(i)](if those children exist).
We store the heap in a simple array and use index math to simulate a complete binary tree:
parent(i) = (i - 1) / 2left(i) = 2*i + 1right(i) = 2*i + 2
The root element is at arr[0] and is always the maximum.
Visually, the heap is always a complete binary tree (all levels filled except maybe the last, and that only from left to right).
class BinaryHeap {
public:
int capacity; // max possible size
int size; // current number of elements
int *arr; // array to store heap elements
BinaryHeap(int cap);
int parent(int i);
int left(int i);
int right(int i);
void swap(int* x, int* y);
void Insert(int x);
void Heapify(int ind);
int getMax();
int ExtractMax();
void IncreaseKey(int i, int val);
void Delete(int i);
void print();
};Pretty classic structure for a heap.
Insert a new key and maintain the max-heap property.
-
Place the new key at the end:
arr[size]. -
“Bubble it up” while it’s greater than its parent:
- Swap with parent.
- Move index up to parent.
-
Stop when:
- It becomes the root (
index == 0), or - Its parent is larger or equal.
- It becomes the root (
void Insert(int x) {
if (size == capacity) {
cout << "Heap Overflow" << endl;
return;
}
arr[size] = x;
int k = size;
size++;
// Bubble up while parent is smaller (max-heap)
while (k != 0 && arr[parent(k)] < arr[k]) {
swap(&arr[parent(k)], &arr[k]);
k = parent(k);
}
}Time Complexity: O(log n) (height of the heap).
Given a node index ind, assume its subtrees are heaps, but arr[ind] might be smaller than one of its children. Fix this violation by “pushing it down”.
-
Compute left and right child indices.
-
Find
largestamongind,left,right. -
If a child is larger than the current node:
- Swap node with the larger child.
- Recursively
Heapify()on that child index.
void Heapify(int ind) {
int li = left(ind);
int ri = right(ind);
int largest = ind;
if (li < size && arr[li] > arr[largest])
largest = li;
if (ri < size && arr[ri] > arr[largest])
largest = ri;
if (largest != ind) {
swap(&arr[ind], &arr[largest]);
Heapify(largest);
}
}Time Complexity: O(log n)
Used in ExtractMax and in heap-building logic (if you add that later).
Return the largest element in the heap.
That’s always at arr[0] in a max-heap.
int getMax() {
if (size == 0) {
cout << "Heap is empty" << endl;
return INT_MIN;
}
return arr[0];
}Time Complexity: O(1).
Remove and return the maximum element (the root).
- Save
arr[0]asmaxi. - Move last element (
arr[size-1]) to root. - Decrease
size. - Call
Heapify(0)to fix the heap property.
int ExtractMax() {
if (size <= 0)
return INT_MIN;
if (size == 1) {
size--;
return arr[0];
}
int maxi = arr[0];
arr[0] = arr[size - 1];
size--;
Heapify(0);
return maxi;
}Time Complexity: O(log n)
In a max-heap, a common operation is to increase the value at index i, and then float it upwards if needed.
-
Set
arr[i] = val(assumingval≥ old value). -
While it is greater than its parent:
- Swap with parent.
- Move
ito parent index.
void IncreaseKey(int i, int val) {
arr[i] = val;
// Bubble up while parent is smaller
while (i != 0 && arr[parent(i)] < arr[i]) {
swap(&arr[parent(i)], &arr[i]);
i = parent(i);
}
}Time Complexity: O(log n)
Note: In a bulletproof version, you’d check
iis in range, and maybe ensureval >= oldValue.
Classic heap trick:
- Increase the value at index
ito +∞ (hereINT_MAX) so it becomes the maximum. - It will bubble up to the root via
IncreaseKey. - Call
ExtractMax()to remove it.
void Delete(int i) {
// Set to very large, move to root, then extract
IncreaseKey(i, INT_MAX);
ExtractMax();
}Time Complexity: O(log n) for IncreaseKey + O(log n) for ExtractMax → still O(log n).
void print() {
for (int i = 0; i < size; i++) {
cout << arr[i] << " ";
}
cout << endl;
}Good for debugging. The heap contents are not sorted, they’re in heap order.
Just re-listing with slight spacing/styling:
#include <bits/stdc++.h>
using namespace std;
class BinaryHeap {
public:
int capacity;
int size;
int *arr;
BinaryHeap(int cap) {
capacity = cap;
size = 0;
arr = new int[capacity];
}
int parent(int i) { return (i - 1) / 2; }
int left(int i) { return 2 * i + 1; }
int right(int i) { return 2 * i + 2; }
void swap(int* x, int* y) {
int temp = *x;
*x = *y;
*y = temp;
}
// Insert into max-heap
void Insert(int x) {
if (size == capacity) {
cout << "Heap Overflow" << endl;
return;
}
arr[size] = x;
int k = size;
size++;
// Bubble up while parent is smaller (for max-heap)
while (k != 0 && arr[parent(k)] < arr[k]) {
swap(&arr[parent(k)], &arr[k]);
k = parent(k);
}
}
// Heapify for max-heap (push down)
void Heapify(int ind) {
int li = left(ind);
int ri = right(ind);
int largest = ind;
if (li < size && arr[li] > arr[largest])
largest = li;
if (ri < size && arr[ri] > arr[largest])
largest = ri;
if (largest != ind) {
swap(&arr[ind], &arr[largest]);
Heapify(largest);
}
}
int getMax() {
if (size == 0) {
cout << "Heap is empty" << endl;
return INT_MIN;
}
return arr[0];
}
int ExtractMax() {
if (size <= 0)
return INT_MIN;
if (size == 1) {
size--;
return arr[0];
}
int maxi = arr[0];
arr[0] = arr[size - 1];
size--;
Heapify(0);
return maxi;
}
// For max-heap we usually INCREASE key to bubble it up.
void IncreaseKey(int i, int val) {
arr[i] = val;
// Bubble up while parent is smaller
while (i != 0 && arr[parent(i)] < arr[i]) {
swap(&arr[parent(i)], &arr[i]);
i = parent(i);
}
}
void Delete(int i) {
// Set to very large, move to root, then extract
IncreaseKey(i, INT_MAX);
ExtractMax();
}
void print() {
for (int i = 0; i < size; i++) {
cout << arr[i] << " ";
}
cout << endl;
}
};
int main() {
BinaryHeap h(20);
h.Insert(4);
h.Insert(1);
h.Insert(2);
h.Insert(6);
h.Insert(7);
h.Insert(3);
h.Insert(8);
h.Insert(5);
cout << "Max value is: " << h.getMax() << endl;
h.Insert(10);
cout << "Max value is: " << h.getMax() << endl;
h.IncreaseKey(3, 20); // increase value at index 3
cout << "Max value is: " << h.getMax() << endl;
h.ExtractMax();
cout << "Max value is: " << h.getMax() << endl;
h.Delete(0);
cout << "Max value is: " << h.getMax() << endl;
return 0;
}If you want to make it more robust/production-ready, you could add:
- A destructor (
~BinaryHeap) todelete[] arr. - Bounds checks in
IncreaseKey,Delete. - Replace raw pointer with
vector<int>.
For a heap with n elements:
| Operation | Time |
|---|---|
Insert |
O(log n) |
Heapify |
O(log n) |
ExtractMax |
O(log n) |
IncreaseKey |
O(log n) |
Delete |
O(log n) |
getMax |
O(1) |
Space: O(capacity).
- You now have both min-heap and max-heap implemented manually — that’s big for understanding
priority_queue. - In C++,
priority_queue<int>is a max-heap by default; your class is essentially a manual version of that. - You can easily template this class to support any comparable type, not just
int.