Open In App

Implement Heap in C++

Last Updated : 08 Jul, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

A heap is a type of tree data structure where each node is either greater than or equal to or less than or equal to the values of its children. Based on this property, heaps are classified into two types:

  • Min Heap: Each node is less than or equal to the values of its children.
  • Max Heap: Each node is greater than or equal to the values of its children.

Additionally, a heap is a complete binary tree, meaning all levels are fully filled except possibly the last level, which is filled from left to right.

In this article, we will learn how to implement the heap data structure in C++ using classes. We will focus on a binary heap. For a k-ary heap, refer to this article – K-ary Heap Data Structure.

Implementation of Heap in C++

In C++, heaps are often stored in arrays for faster access and modification. Due to the complete binary tree property, the index of the child and parent nodes can be easily computed:

  • Left child: 2 * i + 1
  • Right child: 2 * i + 2
  • Parent: (i - 1) / 2

All indices assume 0-based indexing.

Heap Representation in C++

In C++, we can create a class with an vector and a size variable to represent the heap. We can implement the required functions as the member functions of this class

class Heap {
private:
std::vector<int> array;
int size;

void heapify(int i);

public:
Heap(int capacity);
void insert(int key);
int extractMax();
int getMax() const;
void deleteKey(int i);
void increaseKey(int i, int newValue);
void printHeap() const;
};

Heap Operations in C++

There are several essential operations used with heaps:

  1. Insert: Adds a new element to the heap while maintaining the heap property (either min or max heap ordering).
  2. Extract Min/Max: Removes and returns the minimum/maximum element from the heap.
  3. Peek: Returns the minimum/maximum element without removing it.
  4. Heapify: Reorganizes a subtree for a given node to ensure the heap property holds.
  5. Delete: Removes a specific element from the heap.
  6. Increase/Decrease Key: Changes the value of an existing element in the heap.
  7. Build Heap: Converts an array into a proper min or max heap.

Heapify Implementation in C++

The heapify function is implemented with the function signature: void Heap::heapify(int i) where i is the index on which heapify is called.

  1. Initialize the largest node as the current node i.
  2. Calculate the left child index as 2 * i + 1.
  3. Calculate the right child index as 2 * i + 2.
  4. Check if the left child exists (is within the array bounds) and is greater than the current largest node.
    • If true, update the largest node to the left child.
  5. Check if the right child exists (is within the array bounds) and is greater than the current largest node.
    • If true, update the largest node to the right child.
  6. If the largest node is not the current node i, swap the current node with the largest node using the std::swap function.
  7. Recursively apply the heapify operation to the subtree rooted at the largest node.

Insert Key Implementation in C++

The insert function is implemented with the function signature: void Heap::insert(int key).

  1. Append the new key to the end of the array.
  2. Initialize the index i as the index of the newly inserted key (last element of the array).
  3. While the key at index i is greater than its parent and i is not the root:
    • Swap the key with its parent.
    • Update i to the parent index.
  4. Continue this process until the heap property is restored.

Extract Max Implementation in C++

The extractMax function is implemented with the function signature: int Heap::extractMax().

  1. Check if the heap is empty. If true, throw an underflow_error.
  2. If the heap has only one element, remove and return that element.
  3. Store the maximum value (root of the heap) in a temporary variable.
  4. Replace the root of the heap with the last element in the array.
  5. Remove the last element from the array.
  6. Apply the heapify operation on the root to restore the heap property.
  7. Return the stored maximum value.

Get Max Implementation in C++

The getMax function is implemented with the function signature: int Heap::getMax() const.

  1. Check if the heap is empty. If true, throw an underflow_error.
  2. Return the root of the heap, which is the maximum value.

Delete Key Implementation in C++

The deleteKey function is implemented with the function signature: void Heap::deleteKey(int i).

  1. Check if the index i is valid (within the array bounds). If not, throw an out_of_range exception.
  2. Replace the key at index i with the last element in the array.
  3. Remove the last element from the array.
  4. Apply the heapify operation on the subtree rooted at index i to restore the heap property.

Increase Key Implementation in C++

The increaseKey function is implemented with the function signature: void Heap::increaseKey(int i, int newValue).

  1. Check if the index i is valid and the new value is greater than the current value. If not, throw an invalid_argument exception.
  2. Update the value at index i to the new value.
  3. While the key at index i is greater than its parent and i is not the root:
    • Swap the key with its parent.
    • Update i to the parent index.
  4. Continue this process until the heap property is restored.

Print Heap Implementation in C++

The printHeap function is implemented with the function signature: void Heap::printHeap() const.

  1. Iterate through each element in the array.
  2. Print each element followed by a space.
  3. Print a newline at the end.

C++ Program to Implement

C++
#include <iostream>
#include <stdexcept>
#include <vector>

using namespace std;

// Class representing a Max-Heap
class Heap {
private:
    // Vector to store heap elements
    vector<int> array;

    // Helper function to maintain the heap property
    void heapify(int i);

public:
    // Default constructor
    Heap() = default;

    // Function to insert a new key into the heap
    void insert(int key);

    // Function to extract the maximum element from the heap
    int extractMax();

    // Function to get the maximum element from the heap
    int getMax() const;

    // Function to delete a key at a given index
    void deleteKey(int i);

    // Function to increase the value of a key at a given
    // index
    void increaseKey(int i, int newValue);

    // Function to print the heap elements
    void printHeap() const;
};

// Helper function to maintain the heap property
void Heap::heapify(int i)
{
    int largest = i;
    int left = 2 * i + 1;
    int right = 2 * i + 2;
    int size = array.size();

    if (left < size && array[left] > array[largest])
        largest = left;

    if (right < size && array[right] > array[largest])
        largest = right;

    if (largest != i) {
        swap(array[i], array[largest]);
        heapify(largest);
    }
}

// Function to insert a new key into the heap
void Heap::insert(int key)
{
    array.push_back(key);
    int i = array.size() - 1;

    while (i != 0 && array[(i - 1) / 2] < array[i]) {
        swap(array[i], array[(i - 1) / 2]);
        i = (i - 1) / 2;
    }
}

// Function to extract the maximum element from the heap
int Heap::extractMax()
{
    if (array.size() <= 0) {
        throw underflow_error("Heap underflow");
    }

    if (array.size() == 1) {
        int root = array[0];
        array.pop_back();
        return root;
    }

    int root = array[0];
    array[0] = array.back();
    array.pop_back();
    heapify(0);

    return root;
}

// Function to get the maximum element from the heap
int Heap::getMax() const
{
    if (array.size() <= 0) {
        throw underflow_error("Heap is empty");
    }
    return array[0];
}

// Function to delete a key at a given index
void Heap::deleteKey(int i)
{
    if (i >= array.size()) {
        throw out_of_range("Invalid index");
    }

    array[i] = array.back();
    array.pop_back();
    heapify(i);
}

// Function to increase the value of a key at a given index
void Heap::increaseKey(int i, int newValue)
{
    if (i >= array.size() || array[i] >= newValue) {
        throw invalid_argument(
            "Invalid index or new value is not greater");
    }

    array[i] = newValue;
    while (i != 0 && array[(i - 1) / 2] < array[i]) {
        swap(array[i], array[(i - 1) / 2]);
        i = (i - 1) / 2;
    }
}

// Function to print the heap elements
void Heap::printHeap() const
{
    for (int val : array)
        cout << val << " ";
    cout << endl;
}

int main()
{
    Heap heap;

    heap.insert(3);
    heap.insert(2);
    heap.insert(15);
    heap.insert(5);
    heap.insert(4);
    heap.insert(45);

    cout << "Max Heap array: ";
    heap.printHeap();

    cout << "Extracted max value: " << heap.extractMax()
         << endl;
    cout << "Max Heap array after extraction: ";
    heap.printHeap();

    return 0;
}

Output
Max Heap array: 45 5 15 2 4 3 
Extracted max value: 45
Max Heap array after extraction: 15 5 3 2 4 

The min heap can be easily implemented using the same algorithms by changing the comparison operator to less than (<).


Next Article
Article Tags :
Practice Tags :

Similar Reads