Max heap


Discover the essentials of Max Heap data structures. Explore how Max Heaps work, their key properties, and learn how to perform operations like insertion, deletion, and heapify with step-by-step examples.

Max heap

Table of contents

A Max-heap is a data structure in which each node is greater than its children. It is a tree-based data structure but implemented as an array.

Max-heaps are commonly used for sorting.

Heap always maintains the heap property. For max-heap heap property will be -

Maintaining heap property (for max-heap) means comparing the left child and right child with the root and among all three, the maximum will become the root.

Max heap property

To understand about heap please refer to this article -

Insertion in max-heap

While insertion we have to maintain the heap properties -

  1. Complete binary tree
  2. Max heap order

Insertion

Take the example of this heap and try to insert a new node -

Max heap example tree

Its representation in the form of an array will be like this -

Max heap example array

Let's insert 70 into this heap

For insertion, add the new element at the end of the array i.e., insert the new element as a leaf node then move the element to its correct position. The correct position is actually where this node will be higher than its children and lower than its parent.

Max heap tree insert 1

Max heap array insert 1

We will do this by comparing this new element to its parent at each step and moving this new upwards until it is higher than its parent.

Max heap tree insert 2

Max heap array insert 2

Do the same steps again. Compare 70 to its new parent and move this to its correct position.

Max heap tree insert 3

Max heap array insert 3

Now 70 is inserted at its correct position.

The time complexity to insert a new element in a heap will be O(h) where h is the height of the tree. The height of a balanced binary tree is log n so the insertion of a new element will take O(log n) time which is better than what we were getting in the case of the Binary tree implementation of heap. That's why it's better to store data in the form of an array for a heap.

The process of moving data up is called percolate up or bubble up or heapify up or sift up.

Remove element from the max heap

This is the main operation of the heap. All the elements will be removed from the 0th index always because the maximum element will always be at index 0. Since we are storing data in such a way.

This is the main purpose of a max heap i.e., whatever data we are storing in the heap we are always sure that while removing the data we will be getting is maximum among all the data stored.

We can say that the maximum element has the highest priority and it will picked up at a given time.

Deletion

Let's try to remove an element from the heap that we created earlier. So, 100 will be removed from the heap since this is the root of max-heap.

Max heap delete tree example

Max heap delete delete array example

But if we will remove the root element then the heap will be disturbed and we will have to do some extra operations. So rather than removing the element directly from the root, replace it with the last element from heap and the replace the last element.

Max heap tree delete 1

Max heap array delete 1

Now the root element is removed from the heap but the heap property is disturbed i.e., not all the root elements are greater than their children.

But that's not a big deal we already know we can do that by just iterating over all the elements comparing the root elements with children and moving the higher element upwards as a root. But this time start with the root element because we know this element is the reason for the disturbance of heap property.

Max heap tree delete 2

Max heap array delete 2

Again let's see if 30 is still smaller than its children then move this downwards.

Max heap tree delete 3

Max heap array delete 3

This is the final heap after removing an element. Time complexity will be O(log n) for removing an element.

The process of moving data down is called percolate down or **bubble down or heapify down or sift down.

Max heap implementation - Recursive

Here, we will implement percolate functionality in recursive way.

Python
class MaxHeap:
    def __init__(self):
        # Initialize an empty list to store the heap elements
        self.heap = []

    def is_empty(self):
        # Check if the heap is empty
        return len(self.heap) == 0

    def get_max(self):
        # Return the maximum element without removing it
        if self.is_empty():
            return None
        return self.heap[0]

    def get_size(self):
        # Return the size of the heap
        return len(self.heap)

    def insert(self, value):
        # Insert the value into the heap
        self.heap.append(value)
        self._percolate_up(len(self.heap) - 1)

    def _percolate_up(self, index):
        # Move the element at the given index up the heap to maintain the heap property
        parent_index = (index - 1) // 2
        if index > 0 and self.heap[index] > self.heap[parent_index]:
            # Swap the current element with its parent if it's greater
            self.heap[index], self.heap[parent_index] = (
                self.heap[parent_index],
                self.heap[index],
            )
            self._percolate_up(parent_index)

    def remove(self):
        # Remove and return the maximum element from the heap (root of the heap)
        if self.is_empty():
            return None

        if len(self.heap) == 1:
            return self.heap.pop()

        root = self.heap[0]
        # Move the last element to the root and percolate down
        self.heap[0] = self.heap.pop()
        self._percolate_down(0)

        return root

    def _percolate_down(self, index):
        # Move the element at the given index down the heap to maintain the heap property
        size = len(self.heap)
        largest = index
        left = 2 * index + 1
        right = 2 * index + 2

        # Check if the left child exists and is greater than the current element
        if left < size and self.heap[left] > self.heap[largest]:
            largest = left

        # Check if the right child exists and is greater than the current largest
        if right < size and self.heap[right] > self.heap[largest]:
            largest = right

        # If the largest element is not the current element, swap and continue percolating down
        if largest != index:
            self.heap[index], self.heap[largest] = self.heap[largest], self.heap[index]
            self._percolate_down(largest)


max_heap = MaxHeap()
max_heap.insert(10)
max_heap.insert(4)
max_heap.insert(9)
max_heap.insert(2)
max_heap.insert(7)

print("Max element peek:", max_heap.get_max())  # Output: 10
print("Max element:", max_heap.remove())  # Output: 10
print("Max element:", max_heap.remove())  # Output: 9
max_heap.insert(5)
print("Max element:", max_heap.remove())  # Output: 7
JavaScript
class MaxHeap {
    constructor() {
        this.heap = [];
    }

    isEmpty() {
        return this.heap.length === 0;
    }

    getMax() {
        if (this.isEmpty()) {
            return null;
        }
        return this.heap[0];
    }

    getSize() {
        return this.heap.length;
    }

    insert(value) {
        this.heap.push(value);
        this.percolateUp(this.heap.length - 1);
    }

    percolateUp(index) {
        const parentIndex = Math.floor((index - 1) / 2);
        if (index > 0 && this.heap[index] > this.heap[parentIndex]) {
            [this.heap[index], this.heap[parentIndex]] = [this.heap[parentIndex], this.heap[index]];
            this.percolateUp(parentIndex);
        }
    }

    remove() {
        if (this.isEmpty()) {
            return null;
        }

        if (this.heap.length === 1) {
            return this.heap.pop();
        }

        const root = this.heap[0];
        this.heap[0] = this.heap.pop();
        this.percolateDown(0);
        return root;
    }

    percolateDown(index) {
        const size = this.heap.length;
        let largest = index;
        const left = 2 * index + 1;
        const right = 2 * index + 2;

        if (left < size && this.heap[left] > this.heap[largest]) {
            largest = left;
        }

        if (right < size && this.heap[right] > this.heap[largest]) {
            largest = right;
        }

        if (largest !== index) {
            [this.heap[index], this.heap[largest]] = [this.heap[largest], this.heap[index]];
            this.percolateDown(largest);
        }
    }
}

// Example usage
const maxHeap = new MaxHeap();
maxHeap.insert(10);
maxHeap.insert(4);
maxHeap.insert(9);
maxHeap.insert(2);
maxHeap.insert(7);

console.log("Max element peek:", maxHeap.getMax());  // Output: 10
console.log("Max element:", maxHeap.remove());       // Output: 10
console.log("Max element:", maxHeap.remove());       // Output: 9
maxHeap.insert(5);
console.log("Max element:", maxHeap.remove());       // Output: 7
Java
import java.util.ArrayList;
import java.util.List;

public class MaxHeap {
    private List<Integer> heap;

    public MaxHeap() {
        heap = new ArrayList<>();
    }

    public boolean isEmpty() {
        return heap.isEmpty();
    }

    public Integer getMax() {
        if (isEmpty()) {
            return null;
        }
        return heap.get(0);
    }

    public int getSize() {
        return heap.size();
    }

    public void insert(int value) {
        heap.add(value);
        percolateUp(heap.size() - 1);
    }

    private void percolateUp(int index) {
        int parentIndex = (index - 1) / 2;
        if (index > 0 && heap.get(index) > heap.get(parentIndex)) {
            swap(index, parentIndex);
            percolateUp(parentIndex);
        }
    }

    public Integer remove() {
        if (isEmpty()) {
            return null;
        }

        if (heap.size() == 1) {
            return heap.remove(heap.size() - 1);
        }

        int root = heap.get(0);
        heap.set(0, heap.remove(heap.size() - 1));
        percolateDown(0);
        return root;
    }

    private void percolateDown(int index) {
        int size = heap.size();
        int largest = index;
        int left = 2 * index + 1;
        int right = 2 * index + 2;

        if (left < size && heap.get(left) > heap.get(largest)) {
            largest = left;
        }

        if (right < size && heap.get(right) > heap.get(largest)) {
            largest = right;
        }

        if (largest != index) {
            swap(index, largest);
            percolateDown(largest);
        }
    }

    private void swap(int i, int j) {
        int temp = heap.get(i);
        heap.set(i, heap.get(j));
        heap.set(j, temp);
    }

    public static void main(String[] args) {
        MaxHeap maxHeap = new MaxHeap();
        maxHeap.insert(10);
        maxHeap.insert(4);
        maxHeap.insert(9);
        maxHeap.insert(2);
        maxHeap.insert(7);

        System.out.println("Max element peek: " + maxHeap.getMax());  // Output: 10
        System.out.println("Max element: " + maxHeap.remove());       // Output: 10
        System.out.println("Max element: " + maxHeap.remove());       // Output: 9
        maxHeap.insert(5);
        System.out.println("Max element: " + maxHeap.remove());       // Output: 7
    }
}
Go
package main

import (
	"fmt"
)

type MaxHeap struct {
	heap []int
}

func NewMaxHeap() *MaxHeap {
	return &MaxHeap{heap: []int{}}
}

func (h *MaxHeap) IsEmpty() bool {
	return len(h.heap) == 0
}

func (h *MaxHeap) GetMax() int {
	if h.IsEmpty() {
		return -1 // or some other indicator of empty heap
	}
	return h.heap[0]
}

func (h *MaxHeap) GetSize() int {
	return len(h.heap)
}

func (h *MaxHeap) Insert(value int) {
	h.heap = append(h.heap, value)
	h.percolateUp(len(h.heap) - 1)
}

func (h *MaxHeap) percolateUp(index int) {
	if index <= 0 {
		return
	}

	parentIndex := (index - 1) / 2

	if h.heap[index] > h.heap[parentIndex] {
		h.heap[index], h.heap[parentIndex] = h.heap[parentIndex], h.heap[index]
		h.percolateUp(parentIndex) // Recursive call
	}
}

func (h *MaxHeap) Remove() int {
	if h.IsEmpty() {
		return -1 // or some other indicator of empty heap
	}

	if len(h.heap) == 1 {
		root := h.heap[0]
		h.heap = h.heap[:0]
		return root
	}

	root := h.heap[0]
	h.heap[0] = h.heap[len(h.heap)-1]
	h.heap = h.heap[:len(h.heap)-1]
	h.percolateDown(0)
	return root
}

func (h *MaxHeap) percolateDown(index int) {
	size := len(h.heap)
	largest := index
	left := 2*index + 1
	right := 2*index + 2

	if left < size && h.heap[left] > h.heap[largest] {
		largest = left
	}

	if right < size && h.heap[right] > h.heap[largest] {
		largest = right
	}

	if largest != index {
		h.heap[index], h.heap[largest] = h.heap[largest], h.heap[index]
		h.percolateDown(largest)
	}
}

func main() {
	maxHeap := NewMaxHeap()
	maxHeap.Insert(10)
	maxHeap.Insert(4)
	maxHeap.Insert(9)
	maxHeap.Insert(2)
	maxHeap.Insert(7)

	fmt.Println("Max element peek:", maxHeap.GetMax())  // Output: 10
	fmt.Println("Max element:", maxHeap.Remove())       // Output: 10
	fmt.Println("Max element:", maxHeap.Remove())       // Output: 9
	maxHeap.Insert(5)
	fmt.Println("Max element:", maxHeap.Remove())       // Output: 7
}
C++
#include <iostream>
#include <vector>

class MaxHeap {
private:
    std::vector<int> heap;

    void percolateUp(int index) {
        // Base case: if index is 0, there's no parent to compare with
        if (index <= 0) {
            return;
        }
    
        int parentIndex = (index - 1) / 2;
    
        // If the current element is greater than its parent, swap and continue
        if (heap[index] > heap[parentIndex]) {
            std::swap(heap[index], heap[parentIndex]);
            percolateUp(parentIndex); // Recursive call
        }
    }

    void percolateDown(int index) {
        int size = heap.size();
        int largest = index;
        int left = 2 * index + 1;
        int right = 2 * index + 2;

        if (left < size && heap[left] > heap[largest]) {
            largest = left;
        }

        if (right < size && heap[right] > heap[largest]) {
            largest = right;
        }

        if (largest != index) {
            std::swap(heap[index], heap[largest]);
            percolateDown(largest);
        }
    }

public:
    MaxHeap() = default;

    bool isEmpty() const {
        return heap.empty();
    }

    int getMax() const {
        if (isEmpty()) {
            return -1; // or some other indicator of empty heap
        }
        return heap[0];
    }

    int getSize() const {
        return heap.size();
    }

    void insert(int value) {
        heap.push_back(value);
        percolateUp(heap.size() - 1);
    }

    int remove() {
        if (isEmpty()) {
            return -1; // or some other indicator of empty heap
        }

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

        int root = heap[0];
        heap[0] = heap.back();
        heap.pop_back();
        percolateDown(0);
        return root;
    }
};

int main() {
    MaxHeap maxHeap;
    maxHeap.insert(10);
    maxHeap.insert(4);
    maxHeap.insert(9);
    maxHeap.insert(2);
    maxHeap.insert(7);

    std::cout << "Max element peek: " << maxHeap.getMax() << std::endl; // Output: 10
    std::cout << "Max element: " << maxHeap.remove() << std::endl;    // Output: 10
    std::cout << "Max element: " << maxHeap.remove() << std::endl;    // Output: 9
    maxHeap.insert(5);
    std::cout << "Max element: " << maxHeap.remove() << std::endl;    // Output: 7

    return 0;
}
Rust
struct MaxHeap {
    heap: Vec<i32>,
}

impl MaxHeap {
    fn new() -> Self {
        MaxHeap { heap: Vec::new() }
    }

    fn is_empty(&self) -> bool {
        self.heap.is_empty()
    }

    fn get_max(&self) -> Option<i32> {
        if self.is_empty() {
            None
        } else {
            Some(self.heap[0])
        }
    }

    fn get_size(&self) -> usize {
        self.heap.len()
    }

    fn insert(&mut self, value: i32) {
        self.heap.push(value);
        self.percolate_up(self.get_size() - 1);
    }

    fn percolate_up(&mut self, index: usize) {
        // Base case: if index is 0, there's no parent to compare with
        if index == 0 {
            return;
        }

        let parent_index = (index - 1) / 2;

        // If the current element is greater than its parent, swap and recurse
        if self.heap[index] > self.heap[parent_index] {
            self.heap.swap(index, parent_index);
            // Recursively call percolate_up with the parent index
            self.percolate_up(parent_index);
        }
    }

    fn remove(&mut self) -> Option<i32> {
        if self.is_empty() {
            return None;
        }

        if self.get_size() == 1 {
            return self.heap.pop();
        }

        let root = self.heap[0];
        self.heap[0] = self.heap.pop().unwrap();
        self.percolate_down(0);
        Some(root)
    }

    fn percolate_down(&mut self, index: usize) {
        let mut largest = index;
        let left = 2 * index + 1;
        let right = 2 * index + 2;
        let size = self.get_size();

        if left < size && self.heap[left] > self.heap[largest] {
            largest = left;
        }

        if right < size && self.heap[right] > self.heap[largest] {
            largest = right;
        }

        if largest != index {
            self.heap.swap(index, largest);
            self.percolate_down(largest);
        }
    }
}

fn main() {
    let mut max_heap = MaxHeap::new();
    max_heap.insert(10);
    max_heap.insert(4);
    max_heap.insert(9);
    max_heap.insert(2);
    max_heap.insert(7);

    println!("Max element peek: {:?}", max_heap.get_max()); // Output: Some(10)
    println!("Max element: {:?}", max_heap.remove());       // Output: Some(10)
    println!("Max element: {:?}", max_heap.remove());       // Output: Some(9)
    max_heap.insert(5);
    println!("Max element: {:?}", max_heap.remove());       // Output: Some(7)
}

Max heap implementation - Iterative

Here, we will implement percolate functionality in iterative way.

Python
class MaxHeap:
    def __init__(self):
        # Initialize an empty list to store the heap elements
        self.heap = []

    def is_empty(self):
        # Check if the heap is empty
        return len(self.heap) == 0

    def get_max(self):
        # Return the maximum element (the root) without removing it
        if self.is_empty():
            return None
        return self.heap[0]

    def get_size(self):
        # Return the size of the heap
        return len(self.heap)

    def insert(self, value):
        # Insert a new value into the heap
        self.heap.append(value)
        self._percolate_up(len(self.heap) - 1)

    def _percolate_up(self, index):
        # Move the element at the given index up the heap to maintain the heap property
        parent_index = (index - 1) // 2
        while index > 0 and self.heap[index] > self.heap[parent_index]:
            # Swap the current element with its parent if it's larger
            self.heap[index], self.heap[parent_index] = (
                self.heap[parent_index],
                self.heap[index],
            )
            index = parent_index
            parent_index = (index - 1) // 2

    def remove(self):
        # Remove and return the maximum element (root of the heap)
        if self.is_empty():
            return None

        if len(self.heap) == 1:
            return self.heap.pop()

        root = self.heap[0]
        # Move the last element to the root and percolate down
        self.heap[0] = self.heap.pop()
        self._percolate_down(0)

        return root

    def _percolate_down(self, index):
        # Move the element at the given index down the heap to maintain the heap property
        size = len(self.heap)
        largest = index
        while True:
            left = 2 * largest + 1
            right = 2 * largest + 2

            if left < size and self.heap[left] > self.heap[largest]:
                largest = left

            if right < size and self.heap[right] > self.heap[largest]:
                largest = right

            if largest != index:
                self.heap[index], self.heap[largest] = (
                    self.heap[largest],
                    self.heap[index],
                )
                index = largest
            else:
                break


max_heap = MaxHeap()
max_heap.insert(10)
max_heap.insert(4)
max_heap.insert(9)
max_heap.insert(2)
max_heap.insert(7)
print("Max element peek:", max_heap.get_max())  # Output: 10
print("Max element:", max_heap.remove())  # Output: 10
print("Max element:", max_heap.remove())  # Output: 9
max_heap.insert(5)
print("Max element:", max_heap.remove())  # Output: 7
JavaScript
class MaxHeap {
    constructor() {
        // Initialize an empty array to store the heap elements
        this.heap = [];
    }

    isEmpty() {
        // Check if the heap is empty
        return this.heap.length === 0;
    }

    getMax() {
        // Return the maximum element (the root) without removing it
        if (this.isEmpty()) {
            return null;
        }
        return this.heap[0];
    }

    getSize() {
        // Return the size of the heap
        return this.heap.length;
    }

    insert(value) {
        // Insert a new value into the heap
        this.heap.push(value);
        this.percolateUp(this.heap.length - 1);
    }

    percolateUp(index) {
        // Move the element at the given index up the heap to maintain the heap property
        let parentIndex = Math.floor((index - 1) / 2);
        while (index > 0 && this.heap[index] > this.heap[parentIndex]) {
            // Swap the current element with its parent if it's larger
            [this.heap[index], this.heap[parentIndex]] = [this.heap[parentIndex], this.heap[index]];
            index = parentIndex;
            parentIndex = Math.floor((index - 1) / 2);
        }
    }

    remove() {
        // Remove and return the maximum element (root of the heap)
        if (this.isEmpty()) {
            return null;
        }

        if (this.heap.length === 1) {
            return this.heap.pop();
        }

        const root = this.heap[0];
        // Move the last element to the root and percolate down
        this.heap[0] = this.heap.pop();
        this.percolateDown(0);

        return root;
    }

    percolateDown(index) {
        // Move the element at the given index down the heap to maintain the heap property
        const size = this.heap.length;
        let largest = index;

        while (true) {
            const left = 2 * largest + 1;
            const right = 2 * largest + 2;

            if (left < size && this.heap[left] > this.heap[largest]) {
                largest = left;
            }

            if (right < size && this.heap[right] > this.heap[largest]) {
                largest = right;
            }

            if (largest !== index) {
                [this.heap[index], this.heap[largest]] = [this.heap[largest], this.heap[index]];
                index = largest;
            } else {
                break;
            }
        }
    }
}

// Example usage:
const maxHeap = new MaxHeap();
maxHeap.insert(10);
maxHeap.insert(4);
maxHeap.insert(9);
maxHeap.insert(2);
maxHeap.insert(7);
console.log("Max element peek:", maxHeap.getMax());  // Output: 10
console.log("Max element:", maxHeap.remove());        // Output: 10
console.log("Max element:", maxHeap.remove());        // Output: 9
maxHeap.insert(5);
console.log("Max element:", maxHeap.remove());        // Output: 7
Java
import java.util.ArrayList;
import java.util.List;

class MaxHeap {
    private List<Integer> heap;

    public MaxHeap() {
        // Initialize an empty list to store the heap elements
        this.heap = new ArrayList<>();
    }

    public boolean isEmpty() {
        // Check if the heap is empty
        return heap.isEmpty();
    }

    public Integer getMax() {
        // Return the maximum element (the root) without removing it
        if (isEmpty()) {
            return null;
        }
        return heap.get(0);
    }

    public int getSize() {
        // Return the size of the heap
        return heap.size();
    }

    public void insert(int value) {
        // Insert a new value into the heap
        heap.add(value);
        percolateUp(heap.size() - 1);
    }

    private void percolateUp(int index) {
        // Move the element at the given index up the heap to maintain the heap property
        int parentIndex = (index - 1) / 2;
        while (index > 0 && heap.get(index) > heap.get(parentIndex)) {
            // Swap the current element with its parent if it's larger
            swap(index, parentIndex);
            index = parentIndex;
            parentIndex = (index - 1) / 2;
        }
    }

    public Integer remove() {
        // Remove and return the maximum element (root of the heap)
        if (isEmpty()) {
            return null;
        }

        if (heap.size() == 1) {
            return heap.remove(heap.size() - 1);
        }

        int root = heap.get(0);
        // Move the last element to the root and percolate down
        heap.set(0, heap.remove(heap.size() - 1));
        percolateDown(0);

        return root;
    }

    private void percolateDown(int index) {
        // Move the element at the given index down the heap to maintain the heap property
        int size = heap.size();
        int largest = index;

        while (true) {
            int left = 2 * largest + 1;
            int right = 2 * largest + 2;

            if (left < size && heap.get(left) > heap.get(largest)) {
                largest = left;
            }

            if (right < size && heap.get(right) > heap.get(largest)) {
                largest = right;
            }

            if (largest != index) {
                swap(index, largest);
                index = largest;
            } else {
                break;
            }
        }
    }

    private void swap(int index1, int index2) {
        int temp = heap.get(index1);
        heap.set(index1, heap.get(index2));
        heap.set(index2, temp);
    }

    // Example usage:
    public static void main(String[] args) {
        MaxHeap maxHeap = new MaxHeap();
        maxHeap.insert(10);
        maxHeap.insert(4);
        maxHeap.insert(9);
        maxHeap.insert(2);
        maxHeap.insert(7);
        System.out.println("Max element peek: " + maxHeap.getMax());  // Output: 10
        System.out.println("Max element: " + maxHeap.remove());        // Output: 10
        System.out.println("Max element: " + maxHeap.remove());        // Output: 9
        maxHeap.insert(5);
        System.out.println("Max element: " + maxHeap.remove());        // Output: 7
    }
}
Go
package main

import "fmt"

type MaxHeap struct {
	heap []int
}

func NewMaxHeap() *MaxHeap {
	return &MaxHeap{heap: []int{}}
}

func (h *MaxHeap) IsEmpty() bool {
	return len(h.heap) == 0
}

func (h *MaxHeap) GetMax() int {
	if h.IsEmpty() {
		return -1 // Returning -1 for an empty heap, could also return an error
	}
	return h.heap[0]
}

func (h *MaxHeap) GetSize() int {
	return len(h.heap)
}

func (h *MaxHeap) Insert(value int) {
	h.heap = append(h.heap, value)
	h.percolateUp(len(h.heap) - 1)
}

func (h *MaxHeap) percolateUp(index int) {
	parentIndex := (index - 1) / 2
	for index > 0 && h.heap[index] > h.heap[parentIndex] {
		h.heap[index], h.heap[parentIndex] = h.heap[parentIndex], h.heap[index]
		index = parentIndex
		parentIndex = (index - 1) / 2
	}
}

func (h *MaxHeap) Remove() int {
	if h.IsEmpty() {
		return -1 // Returning -1 for an empty heap, could also return an error
	}

	if len(h.heap) == 1 {
		return h.heap[0]
	}

	root := h.heap[0]
	h.heap[0] = h.heap[len(h.heap)-1]
	h.heap = h.heap[:len(h.heap)-1]
	h.percolateDown(0)

	return root
}

func (h *MaxHeap) percolateDown(index int) {
	size := len(h.heap)
	largest := index

	for {
		left := 2*largest + 1
		right := 2*largest + 2

		if left < size && h.heap[left] > h.heap[largest] {
			largest = left
		}

		if right < size && h.heap[right] > h.heap[largest] {
			largest = right
		}

		if largest != index {
			h.heap[index], h.heap[largest] = h.heap[largest], h.heap[index]
			index = largest
		} else {
			break
		}
	}
}

func main() {
	maxHeap := NewMaxHeap()
	maxHeap.Insert(10)
	maxHeap.Insert(4)
	maxHeap.Insert(9)
	maxHeap.Insert(2)
	maxHeap.Insert(7)
	fmt.Println("Max element peek:", maxHeap.GetMax()) // Output: 10
	fmt.Println("Max element:", maxHeap.Remove())      // Output: 10
	fmt.Println("Max element:", maxHeap.Remove())      // Output: 9
	maxHeap.Insert(5)
	fmt.Println("Max element:", maxHeap.Remove())      // Output: 7
}
C++
#include <iostream>
#include <vector>
#include <stdexcept>

class MaxHeap {
private:
    std::vector<int> heap;

    void percolateUp(int index) {
        int parentIndex = (index - 1) / 2;
        while (index > 0 && heap[index] > heap[parentIndex]) {
            std::swap(heap[index], heap[parentIndex]);
            index = parentIndex;
            parentIndex = (index - 1) / 2;
        }
    }

    void percolateDown(int index) {
        int size = heap.size();
        int largest = index;

        while (true) {
            int left = 2 * largest + 1;
            int right = 2 * largest + 2;

            if (left < size && heap[left] > heap[largest]) {
                largest = left;
            }

            if (right < size && heap[right] > heap[largest]) {
                largest = right;
            }

            if (largest != index) {
                std::swap(heap[index], heap[largest]);
                index = largest;
            } else {
                break;
            }
        }
    }

public:
    bool isEmpty() const {
        return heap.empty();
    }

    int getMax() const {
        if (isEmpty()) {
            throw std::runtime_error("Heap is empty");
        }
        return heap[0];
    }

    int getSize() const {
        return heap.size();
    }

    void insert(int value) {
        heap.push_back(value);
        percolateUp(heap.size() - 1);
    }

    int remove() {
        if (isEmpty()) {
            throw std::runtime_error("Heap is empty");
        }

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

        int root = heap[0];
        heap[0] = heap.back();
        heap.pop_back();
        percolateDown(0);

        return root;
    }
};

int main() {
    MaxHeap maxHeap;
    maxHeap.insert(10);
    maxHeap.insert(4);
    maxHeap.insert(9);
    maxHeap.insert(2);
    maxHeap.insert(7);
    std::cout << "Max element peek: " << maxHeap.getMax() << std::endl; // Output: 10
    std::cout << "Max element: " << maxHeap.remove() << std::endl;      // Output: 10
    std::cout << "Max element: " << maxHeap.remove() << std::endl;      // Output: 9
    maxHeap.insert(5);
    std::cout << "Max element: " << maxHeap.remove() << std::endl;      // Output: 7

    return 0;
}
Rust
pub struct MaxHeap {
    heap: Vec<i32>,
}

impl MaxHeap {
    // Create a new empty MaxHeap
    pub fn new() -> Self {
        MaxHeap { heap: Vec::new() }
    }

    // Check if the heap is empty
    pub fn is_empty(&self) -> bool {
        self.heap.is_empty()
    }

    // Get the maximum element from the heap (root)
    pub fn get_max(&self) -> Option<i32> {
        self.heap.first().copied()
    }

    // Get the size of the heap
    pub fn get_size(&self) -> usize {
        self.heap.len()
    }

    // Insert a value into the heap
    pub fn insert(&mut self, value: i32) {
        self.heap.push(value);
        self.percolate_up(self.heap.len() - 1);
    }

    // Remove and return the maximum element from the heap
    pub fn remove(&mut self) -> Option<i32> {
        if self.is_empty() {
            return None;
        }
        if self.heap.len() == 1 {
            return self.heap.pop();
        }
        let root = self.heap[0];
        self.heap[0] = self.heap.pop().unwrap();
        self.percolate_down(0);
        Some(root)
    }

    // Percolate an element up the heap
    fn percolate_up(&mut self, index: usize) {
        let mut index = index;
        while index > 0 {
            let parent_index = (index - 1) / 2;
            if self.heap[index] > self.heap[parent_index] {
                self.heap.swap(index, parent_index);
                index = parent_index;
            } else {
                break;
            }
        }
    }

    // Percolate an element down the heap
    fn percolate_down(&mut self, index: usize) {
        let size = self.heap.len();
        let mut index = index;

        loop {
            let left = 2 * index + 1;
            let right = 2 * index + 2;
            let mut largest = index;

            if left < size && self.heap[left] > self.heap[largest] {
                largest = left;
            }

            if right < size && self.heap[right] > self.heap[largest] {
                largest = right;
            }

            if largest != index {
                self.heap.swap(index, largest);
                index = largest;
            } else {
                break;
            }
        }
    }
}

fn main() {
    let mut max_heap = MaxHeap::new();
    max_heap.insert(10);
    max_heap.insert(4);
    max_heap.insert(9);
    max_heap.insert(2);
    max_heap.insert(7);

    println!("Max element peek: {:?}", max_heap.get_max()); // Output: Some(10)
    println!("Max element: {:?}", max_heap.remove());      // Output: Some(10)
    println!("Max element: {:?}", max_heap.remove());      // Output: Some(9)
    max_heap.insert(5);
    println!("Max element: {:?}", max_heap.remove());      // Output: Some(7)
}

Output

Max element peek: 10
Max element: 10
Max element: 9
Max element: 7

Using the heap push (insertion new element) we can create a heap if we are getting elements. In case we already have an array then we can convert it into a heap using Heapify method. We will discuss this later while learning about when and why to use Heapify.

OperationWorst Case
Get maxO(1)
DeleteO(log n)
InsertO(log n)

For full implementation to create heap from an array using heapify check this -


Recommended Posts