input: Write a python function to implement a MinHeap class that supports insertion and extraction of the minimum element.
  assert heap.insertKey(3) == None
  assert heap.insertKey(2) == None
  assert heap.insertKey(15) == None
  assert heap.extractMin() == 2
  assert heap.extractMin() == 3
  assert heap.insertKey(5) == None
  assert heap.insertKey(4) == None
  assert heap.extractMin() == 4
output: class MinHeap:
      def __init__(self):
          self.heap = []
  
      def insertKey(self, key):
          self.heap.append(key)
          self._heapify_up(len(self.heap) - 1)
  
      def extractMin(self):
          if len(self.heap) == 0:
              return None
          min_elem = self.heap[0]
          last_elem = self.heap.pop()
          if len(self.heap) > 0:
              self.heap[0] = last_elem
              self._heapify_down(0)
          return min_elem
  
      def _heapify_up(self, index):
          parent_index = (index - 1) // 2
          if index > 0 and self.heap[index] < self.heap[parent_index]:
              self.heap[index], self.heap[parent_index] = self.heap[parent_index], self.heap[index]
              self._heapify_up(parent_index)
  
      def _heapify_down(self, index):
          smallest = index
          left_child = 2 * index + 1
          right_child = 2 * index + 2
  
          if left_child < len(self.heap) and self.heap[left_child] < self.heap[smallest]:
              smallest = left_child
          if right_child < len(self.heap) and self.heap[right_child] < self.heap[smallest]:
              smallest = right_child
  
          if smallest != index:
              self.heap[index], self.heap[smallest] = self.heap[smallest], self.heap[index]
              self._heapify_down(smallest)
  
  heap = MinHeap()
  assert heap.insertKey(3) == None
  assert heap.insertKey(2) == None
  assert heap.insertKey(15) == None
  assert heap.extractMin() == 2
  assert heap.extractMin() == 3
  assert heap.insertKey(5) == None
  assert heap.insertKey(4) == None
  assert heap.extractMin() == 4