Algorithms

Min Heap Construction

6 months, 3 weeks ago ; 102 views
Share this

Min Heap Construction

A MinHeap is a binary tree-based data structure where the value of each node is less than or equal to the values of its children.

To successfully construct a Min heap, you will have to master the following methods:~

  •  Build Heap
  •  Sift Down
  •  Sift Up
  •  Insert
  •  Remove

Problem

In this solution, I am solving the problem of implementing the functionality of a MinHeap, which allows for efficient insertion, removal of the minimum element (root), and maintaining the heap property.

class MinHeap:
    """
    A class representing a MinHeap data structure.

    Attributes:
        heap (list): The list representing the binary heap.
    """

    def __init__(self, array):
        """
        Initializes a MinHeap object with the given array.

        Args:
            array (list): The array to be converted into a MinHeap.
        """
        self.heap = self.build_heap(array)

    def build_heap(self, array):
        """
        Builds a MinHeap from the given array.

        Args:
            array (list): The array to be converted into a MinHeap.

        Returns:
            list: The array representing the MinHeap.
        """
        first_parent_idx = (len(array) - 2) // 2
        for current_idx in reversed(range(first_parent_idx)):
            self.sift_down(current_idx, len(array) - 1, array)
        return array

    def sift_down(self, current_idx, end_idx, heap):
        """
        Performs a sift down operation on the heap.

        Args:
            current_idx (int): The index of the current node.
            end_idx (int): The index of the last node in the heap.
            heap (list): The list representing the binary heap.
        """
        child_one_idx = current_idx * 2 + 1
        while child_one_idx <= end_idx:
            child_two_idx = current_idx * 2 + 2 if current_idx * 2 + 2 <= end_idx else -1
            if child_two_idx != -1 and heap[child_two_idx] < heap[child_one_idx]:
                idx_to_swap = child_two_idx
            else:
                idx_to_swap = child_one_idx
            if heap[idx_to_swap] < heap[current_idx]:
                self.swap(current_idx, idx_to_swap, heap)
                current_idx = idx_to_swap
                child_one_idx = current_idx * 2 + 1
            else:
                break

    def sift_up(self, current_idx, heap):
        """
        Performs a sift up operation on the heap.

        Args:
            current_idx (int): The index of the current node.
            heap (list): The list representing the binary heap.
        """
        parent_idx = (current_idx - 1) // 2
        while current_idx > 0 and heap[current_idx] < heap[parent_idx]:
            self.swap(current_idx, parent_idx, heap)
            current_idx = parent_idx
            parent_idx = (current_idx - 1) // 2

    def remove(self):
        """
        Removes and returns the minimum element from the heap.

        Returns:
            int: The minimum element removed from the heap.
        """
        self.swap(0, len(self.heap) - 1, self.heap)
        value_to_remove = self.heap.pop()
        self.sift_down(0, len(self.heap) - 1, self.heap)
        return value_to_remove

    def insert(self, value):
        """
        Inserts a new element into the heap.

        Args:
            value (int): The value to be inserted into the heap.
        """
        self.heap.append(value)
        self.sift_up(len(self.heap) - 1, self.heap)

    def swap(self, i, j, heap):
        """
        Swaps the elements at the given indices in the heap.

        Args:
            i (int): The index of the first element.
            j (int): The index of the second element.
            heap (list): The list representing the binary heap.
        """
        heap[i], heap[j] = heap[j], heap[i]

Approach

The solution uses the binary heap data structure to implement the MinHeap. Here's a brief overview of each method:

__init__ method

Initializes the MinHeap with an array of elements and builds the heap using the buildHeap method.

buildHeap

Builds the heap from an input array by repeatedly calling siftDown starting from the last parent node.

siftDown

Corrects a single violation of the heap property by swapping a node with its smaller child recursively until the heap property is restored.

siftUp

Continuously swaps the current node that we've inserted with its parent nodes until it's in its' correct position. By so doing, the heap property is restored.

remove

Removes and returns the minimum element from the heap (the root), and restores the heap property by calling siftDown.

insert

Inserts a new element into the heap, restores the heap property by calling siftUp.

swap

Swaps the elements at two given indices in the heap.

Time & Space Complexity

Let's analyze the time and space complexity of each method in the MinHeap class:

 __init__ method

The __init__ method calls the build_heap method, which has a time complexity of O(n), where n is the number of elements in the input array.

build_heap method

The build_heap method iterates through each node of the binary heap and calls the sift_down method for each node. Since the sift_down operation has a time complexity of O(log(n)), where n is the number of elements in the heap, the overall time complexity of build_heap is O(n *(log n)).

sift_down method

The sift_down method performs a series of comparisons and swaps while traversing down the heap, maintaining the heap property. In the worst case, it performs a logarithmic number of operations, so the time complexity is logarithmic i.e. Log N where N is the number of elements in the heap.

sift_up method

The sift_up method performs a series of comparisons and swaps while traversing up the heap, maintaining the heap property. In the worst case, it performs a logarithmic number of operations, so the time complexity is logarithmic i.e. Log N where N is the number of elements in the heap.


remove method

The remove method removes the minimum element from the heap and then performs a sift_down operation to maintain the heap property. Both removing the minimum element and performing sift_down have a time complexity of logarithmic i.e. Log N where N is the number of elements in the heap.

insert method

The insert method adds a new element to the heap and then performs a sift_up operation to maintain the heap property. Both adding the element and performing sift_up have a logarithmic time complexity i.e. Log N where N is the number of elements in the heap.

swap method

The swap method performs a constant number of operations, so the time complexity is O(1).

For all the methods above (swap, insert, remove, sift_up, sift_down, build_heap), the space Complexity is O(1) since no additional space is used.

Unit Tests

Below I explore unit tests using Python's unittest module to test the correctness and robustness of the MinHeap class:

These unit tests cover various scenarios:

  •     Building the heap from an unsorted array.
  •     Performing the siftDown operation after removing the minimum element.
  •     Performing the siftUp operation after inserting a new element.
  •     Removing the minimum element from the heap.
  •     Inserting a new element into the heap.

Each test case asserts whether the MinHeap class behaves correctly for a given operation. These tests help ensure the correctness and robustness of the solution.

 

Use Cases

MinHeaps are commonly used in various scenarios such as:

  •     Implementing priority queues.
  •     Implementing algorithms like Dijkstra's shortest path algorithm and Prim's minimum spanning tree algorithm.
  •     Efficiently finding the k smallest (or largest) elements in an array.

Application

The MinHeap data structure implemented by this solution can be used whenever we need to maintain a collection of elements with efficient insertion and removal of the minimum element.

Become a member
Get the latest news right in your inbox. We never spam!

Read next

Island Perimeter

&nbsp;This solution seeks to find the perimeter of an island in a grid.&nbsp; The problem considers a grid where each cell represents land (1) or … Read More

Kibsoft 5 months, 3 weeks ago . 119 views

Pacific Atlantic Waterflow

5 months, 3 weeks ago . 119 views