C++ Program to Implement Max Heap



In this article, we will write a C++ program that implements a Max Heap. A Max Heap is a binary tree where the value of each node is greater than or equal to the values of its children. We will explain how to create a Max Heap using arrays and implement operations like insertion and deletion. The article will cover the following topics:

What is a Heap?

A heap is a tree-based data structure that follows a specific rule called the heap property. It is always a complete binary tree, meaning all levels are fully filled, except possibly the last one, which is filled from left to right.

Types of Heaps

Heaps can be classified into two types based on their properties:

  • Max Heap: In a max heap, the value of each parent node is greater than or equal to the values of its children. This ensures that the largest element is always at the root.
  • Min Heap: In a min heap, the value of each parent node is less than or equal to the values of its children. This ensures that the smallest element is always at the root.

Representing Heaps

Before we look at heap operations, let's understand how heaps can be represented. A common way is by using arrays. Since heaps form complete binary trees, there is no wasted space. For example, the max heap with elements (30, 20, 15, 5, 10, 12, 6) can be represented as an array.

Declaring a Heap: To declare a heap, we use this structure:

struct Heap {
   int *array;    // Array to store heap elements
   int count;     // Number of elements in the heap
   int capacity;  // Size of the heap
   int heap_type; // Type of heap (Min or Max)
};

Creating a Heap: To create a heap, we use a function that allocates memory for the heap structure and the array of elements. Here's how it we can create a heap:

struct Heap* CreateHeap(int capacity, int heap_type) {
   // Allocate memory for the heap structure
   struct Heap* h = (struct Heap*)malloc(sizeof(struct Heap));
   if (h == NULL) {  // Check if memory allocation for heap failed
        printf("Memory Error");
        return NULL;
    }

    // Initialize heap properties
    h->heap_type = heap_type;  // Set heap type (Min or Max)
    h->count = 0;              // Set the initial count of elements to 0
    h->capacity = capacity;    // Set the maximum capacity of the heap
    h->array = (int*)malloc(sizeof(int) * h->capacity);  // Allocate memory for the heap array

    if (h->array == NULL) {  // Check if memory allocation for the array failed
        printf("Memory Error");
        return NULL;
    }

    return h;  // Return the created heap
}   

Time Complexity: The time complexity of creating a heap is O(1).

What is Max Heap?

A Max Heap is a complete binary tree where each parent node has a value greater than or equal to its children, ensuring that the largest element is always at the root.

Key points about Max Heap:

  • The root node contains the largest element.
  • It is a complete binary tree, with all levels fully filled except possibly the last, and nodes are filled from left to right.
  • For any node at index i, the left child is at index 2i + 1, and the right child is at index 2i + 2.
Max heap visualization

What is Heapify?

Heapify is the process used to maintain the heap property in a binary heap. When a new element is added to the heap, it might not satisfy the heap property. In such cases, heapify helps to fix this by adjusting the heap structure.

For example, in a max-heap, the parent node should always be greater than or equal to its children. If a parent node is smaller than its child, heapify swaps them. This process repeats until the heap property is restored.

Example of Heapify

Consider the following heap before heapifying:

In this heap, the heap property is violated because element 1 is smaller than its parent, 31. Additionally, 1 is not in the correct position according to the heap property. To fix this, we start heapifying from element 1, comparing it with its children and moving it down the tree until the heap property is restored.

Heapify Process:

  • Start with element 1. Compare it with its children, 9 and 10. Since 1 is smaller than both, we swap it with the larger child, which is 10:
  • Next, compare element 1 with its new children, 8 and 7. We swap 1 with the larger child, 8:
  • heapify first part
  • Now, the heap property is satisfied, as each parent is greater than or equal to its children. This process, where we move from top to bottom adjusting the elements, is called percolating down.

Max Heap Implementation

We represent the Max Heap using an array. The parent-child relationships are as follows:

  • The parent of a node at index i is at index (i - 1) / 2.
  • The left child of a node at index i is at index 2 * i + 1.
  • The right child of a node at index i is at index 2 * i + 2.

Max Heap Insert Operation

When we insert a new element, we place it at the end of the array. Then, we "heapify" it upwards to maintain the max-heap property. If the new element is larger than its parent, we swap them. This continues until the heap property is satisfied.

Steps for Insertion:

  • We add the new element at the end of the heap.
  • We heapify the element by comparing it with its parent and swapping if needed.
  • We repeat this process until the element is in the correct position or reaches the root.
Implementation of Max Heap

Example

Below is the C++ code to implement a Max Heap, where we use the MaxHeap class with a vector to store elements. The insert function adds a new element and places it in the correct position. The heapify function ensures that the max heap property is maintained by swapping elements as needed. The display function shows the current state of the heap.

#include <iostream>
#include <vector>
using namespace std;

class MaxHeap {
private:
    vector<int> heap;

    // Function to heapify the tree
    void heapify(int index) {
        int left = 2 * index + 1;  // Left child index
        int right = 2 * index + 2; // Right child index
        int largest = index;

        // If left child is greater than root
        if (left < heap.size() && heap[left] > heap[largest]) {
            largest = left;
        }

        // If right child is greater than the largest so far
        if (right < heap.size() && heap[right] > heap[largest]) {
            largest = right;
        }

        // If the largest is not the root
        if (largest != index) {
            swap(heap[index], heap[largest]);
            heapify(largest); // Recursively heapify the affected sub-tree
        }
    }

public:
    // Function to insert an element into the heap
    void insert(int value) {
        // Step 1: Add the new element at the end of the heap
        heap.push_back(value);

        // Step 2: Get the index of the newly added element
        int index = heap.size() - 1;

        // Step 3: Move the element up to its correct position in the heap
        while (index != 0 && heap[(index - 1) / 2] < heap[index]) {
            // Swap with the parent if current node is larger
            swap(heap[index], heap[(index - 1) / 2]);
            index = (index - 1) / 2; // Move to the parent's index
        }
    }

    // Function to display the heap
    void display() {
        for (int i = 0; i < heap.size(); ++i) {
            cout << heap[i] << " "; // Print each element in the heap
        }
        cout << endl;
    }
};

int main() {
    MaxHeap maxHeap;

    // Insert elements into the heap
    maxHeap.insert(6);  // Inserting 6 into the heap
    maxHeap.display(); 
    maxHeap.insert(4);  // Inserting 4 into the heap
    maxHeap.display(); 
    maxHeap.insert(9);  // Inserting 9 into the heap
    maxHeap.display(); 
    maxHeap.insert(3);  // Inserting 3 into the heap
    maxHeap.display(); 
    maxHeap.insert(2);  // Inserting 2 into the heap
    maxHeap.display(); 

    // Display the heap after insertions
    cout << "Max Heap after insertions: ";
    maxHeap.display();  // Print the final Max Heap

    return 0;
}

Below is the output showing the state of the Max Heap after each insertion, followed by the final heap after all insertions are complete:

6 
6 4 
9 4 6 
9 4 6 3 
9 4 6 3 2 
Max Heap after insertions: 9 4 6 3 2 

Time Complexity: O(m log n) for inserting m elements.

Space Complexity: O(n), because we store the elements in the heap array.

Deletion from Max Heap (Extract Max)

To delete an element from the Max Heap, we simply remove the root (largest element). After removing the root, we replace it with the last element in the heap and remove the last element. Finally, we heapify the tree to restore the heap property.

Steps for Extract Max:

  • We remove the root(largest element).
  • We replace the root with the last element and remove the last element.
  • We heapify the tree by starting from the root, comparing it with its children, and swapping it with the larger child if needed. We continue this until the heap property is restored.
Deletion from max heap Process Deletion from max heap Process

Example

Here's a complete C++ code for the deletion operation in Max Heap, where we first insert elements. Then, to delete the root (largest element), we replace it with the last element in the heap and remove the last element. Finally, we heapify the tree starting from the root to restore the Max Heap property.

#include <iostream>
#include <vector>
using namespace std;

class MaxHeap {
private:
    vector<int> heap;

    // Function to heapify the tree to maintain the Max Heap property
    void heapify(int index) {
        int left = 2 * index + 1;  // Left child index
        int right = 2 * index + 2; // Right child index
        int largest = index;

        // If left child is larger than root
        if (left < heap.size() && heap[left] > heap[largest]) {
            largest = left;
        }

        // If right child is larger than the largest so far
        if (right < heap.size() && heap[right] > heap[largest]) {
            largest = right;
        }

        // If the largest is not the root
        if (largest != index) {
            swap(heap[index], heap[largest]);
            heapify(largest); // Recursively heapify the affected sub-tree
        }
    }

public:
    // Function to insert an element into the heap
    void insert(int value) {
        heap.push_back(value);  // Step 1: Add the new element at the end
        
        int index = heap.size() - 1; // Get the index of the newly added element
        
        // Step 2: Move the element up to its correct position in the heap
        while (index != 0 && heap[(index - 1) / 2] < heap[index]) {
            // Swap with the parent if current node is larger
            swap(heap[index], heap[(index - 1) / 2]);
            index = (index - 1) / 2; // Move to the parent's index
        }
    }

    // Function to extract the maximum element (root) from the heap
    int extractMax() {
        if (heap.empty()) return -1; // Heap is empty, return -1 as an error value
        
        int max = heap[0]; // Root element (largest element)
        heap[0] = heap.back(); // Replace the root with the last element in the heap
        heap.pop_back(); // Remove the last element
        
        // Heapify the root to restore the heap property
        heapify(0);
        
        return max; // Return the largest element that was removed
    }

    // Function to display the heap
    void display() {
        for (int i = 0; i < heap.size(); ++i) {
            cout << heap[i] << " ";
        }
        cout << endl;
    }
};

int main() {
    MaxHeap maxHeap;

    // Insert elements into the heap
    maxHeap.insert(6);  // Inserting 6 into the heap
    maxHeap.insert(4);  // Inserting 4 into the heap
    maxHeap.insert(9);  // Inserting 9 into the heap
    maxHeap.insert(3);  // Inserting 3 into the heap
    maxHeap.insert(2);  // Inserting 2 into the heap

    cout << "Max Heap after insertions: ";
    maxHeap.display();  // Display the heap after insertions
    
    // Perform Extract Max operation (remove the largest element)
    cout << "Extracted Max: " << maxHeap.extractMax() << endl;

    // Display the heap after Extract Max
    cout << "Max Heap after Extract Max: ";
    maxHeap.display();  // Display the heap after removal of the root element
    return 0;
}

Here's the output showing the Max Heap after inserting elements and after removing the largest element:

Max Heap after insertions: 9 4 6 3 2 
Extracted Max: 9
Max Heap after Extract Max: 6 4 2 3 

Time Complexity: O(log n), because we need to heapify the tree after removal.

Space Complexity: O(n), for showing the heap elements.

Conclusion

In this article, we have successfully implemented a Max Heap in C++ by covering key concepts such as insertion, deletion, and heapifying. We also looked at how to keep the heap property intact, making sure the largest element stays at the root. By using arrays to represent the heap, we performed the operations effectively and showed how to manage a Max Heap.

Updated on: 2025-03-07T15:35:32+05:30

13K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements