Heap

Page content

Heap

Heap is a special Tree-based data structure in which tree is a complete binary tree. Heaps are basically are binary trees with more properties and specifications and there are mainly two types of heaps.

Rules

  • A heap must be a complete binary tree.
    • All of the levels of the tree must be completely filled except maybe the last one.
    • The last level has all keys as left as possible

Types of heap

Min Heap

In min heap, all elements are smaller than their children. The root node will be the smallest element.

Max Heap

In max heap, all elements are bigger than their children. The root node will be the biggest element.

Query Suggestion

Implementation

# A Binary Heap is a Complete Binary Tree. A binary heap is typically represented as array. The representation is done as:

# The root element will be at Arr[0].
# Below table shows indexes of other nodes for the ith node, i.e., Arr[i]:
# Arr[(i-1)/2] Returns the parent_idx node
# Arr[(2*i)+1] Returns the left child node
# Arr[(2*i)+2] Returns the right child node

import sys

class MinHeap:
    def __init__(self, maxsize):
        self.maxsize = maxsize
        # Initialize the first value with the smallest value
        # With this first value, calculation to get parent_idx and children gets a little simpler
        self.heap_list = [0] * (maxsize + 1)
        self.heap_list[0] = -1 * sys.maxsize
        self.size = 0
        # Actual root index
        self.ROOT_IDX = 1

    def parent_idx(self, idx):
        return idx // 2

    def left_child_idx(self, idx):
        return 2 * idx

    def right_child_idx(self, idx):
        return (2 * idx) + 1

    def is_leaf(self, idx):
        # If left child index is bigger than self.size, it means there is no child as this is a complete binary tree
        return 2 * idx > self.size

    def swap(self, fi, si):
        self.heap_list[fi], self.heap_list[si] = self.heap_list[si], self.heap_list[fi]

    # Heapify the value in the given idx from top to bottom
    def min_heapify(self, idx):
        li = self.left_child_idx(idx)
        ri = self.right_child_idx(idx)
        curr = self.heap_list[idx]
        if not self.is_leaf(idx):
            l, r = self.heap_list[li], self.heap_list[ri]
            if l < curr or r < curr:
                if l < r:
                    self.swap(idx, li)
                    self.min_heapify(li)
                else:
                    self.swap(idx, ri)
                    self.min_heapify(ri)

 	# O(Log n)
    def insert(self, new_el):
        if self.size >= self.maxsize:
            print("Heap maxsize exceeded")
            return
        self.size += 1
        self.heap_list[self.size] = new_el
        tail_idx = self.size
        pi = self.parent_idx(tail_idx)
        # Heapify the inserted value from bottom to top while it's bigger than the parent
        while self.heap_list[tail_idx] < self.heap_list[pi]:
            self.swap(tail_idx, pi)
            tail_idx = pi
            pi = self.parent_idx(tail_idx)

	# O(Log n)
    def extract_min(self):
        if self.size < 1:
            print("Empty Heap")
            return
        min_ele = self.heap_list[self.ROOT_IDX]
        # Swap the root with the last element
        self.heap_list[self.ROOT_IDX] = self.heap_list[self.size]
        self.size -= 1
		# Heapify heap_list from top to bottom
        self.min_heapify(self.ROOT_IDX)
        return min_ele

	# O(1)
	def get_min(self):
        if self.size < 1:
            print("Empty Heap")
            return
        return self.heap_list[self.ROOT_IDX]

Reference

Heap Data Structure Data Structures: Heaps Learning to Love Heaps Heap implementation in Python