Hello! Welcome to your next lesson.
In our last few sessions, we dove deep into search trees, culminating in the implementation of AVL trees. We saw how they use rotations to maintain a strict balance, guaranteeing for searching, inserting, and deleting any element.
Today, we shift our focus from general-purpose search trees to a more specialized, but incredibly powerful, tree-based data structure: the binary heap. While a search tree is optimized for finding any value quickly, a heap is optimized for one primary task: finding the minimum or maximum element in a collection instantly.
Your learning outcome for this lesson is to implement a binary heap (max-heap and min-heap) using an array. This is a fundamental data structure for technical interviews and a building block for priority queues, heap sort, and many advanced graph algorithms.
1. What is a Binary Heap?
A binary heap is a binary tree that satisfies two specific properties. Understanding these properties is the key to implementing the structure correctly.
-
Structure Property: A Complete Binary Tree
A heap must be a complete binary tree. This means all levels of the tree are filled, except possibly the last level, which is filled from left to right without any gaps. -
Heap Property: Min-Heap or Max-Heap
This property defines the relationship between a parent and its children.- Min-Heap: The value of any node is less than or equal to the values of its children. This ensures the smallest element is always at the root of the tree.
- Max-Heap: The value of any node is greater than or equal to the values of its children. This ensures the largest element is always at the root.

To solidify these concepts, let's watch a short, clear explanation.
Heap Explained and Implemented in Java | Maximum and Minimum Heaps | Priority Queues | Geekific
The video 'Heap Explained and Implemented in Java' from the Geekific channel provides an excellent introduction to what heaps are.
Watch from 00:23 to 01:28. This clip clearly defines the complete binary tree property and visually distinguishes between a maximum and a minimum heap.
This structure is what makes heaps so efficient for their intended purpose. The ability to find the min or max element in time is a direct consequence of the heap property. This makes them the ideal data structure for implementing Priority Queues, where you always need to process the item with the highest (or lowest) priority first.
2. The Array-Based Representation
Although we visualize heaps as trees, their "complete" nature makes them perfectly suited for implementation using a simple array (or an ArrayList in Java). We don't need Node objects with left and right pointers.
How does this work? We store the tree elements level by level, from left to right, in an array.
Given a node at index i in a 0-indexed array:
- Its parent is at index
(i - 1) / 2. - Its left child is at index
2 * i + 1. - Its right child is at index
2 * i + 2.
These simple formulas allow us to navigate the tree structure using array indices alone, which is highly efficient.
Heap Explained and Implemented in Java | Maximum and Minimum Heaps | Priority Queues | Geekific
Let's watch another clip from the same Geekific video that explains this array representation.
Watch from 02:47 to 04:08. Pay close attention to how the tree is mapped to the array and how the formulas are used to find a node's parent and children.
3. Implementing Heap Operations
Now for the core of the lesson: implementing the main operations. We'll focus on a min-heap first. The logic for a max-heap is nearly identical, just with the comparisons flipped.
The two main operations are insert and extractMin (removing the root). The challenge is to perform these operations while maintaining both the structure and heap properties. This is done through two helper processes often called "bubbling" or "percolating".
3.1 Insertion and percolateUp
To insert a new element into a min-heap:
- Add to the end: Place the new element at the first available spot in the array. This maintains the complete binary tree structure.
- Fix the heap property: The new element might be smaller than its parent, violating the min-heap property. To fix this, we "percolate up" (or "bubble up"). We compare the new element with its parent and swap them if they are in the wrong order. We repeat this process, moving the element up the tree until it's in its correct position (i.e., its parent is smaller than it, or it has reached the root).
This process ensures the operation takes time, as the height of a complete binary tree with N nodes is .
Let's see a dry run of this upheap process.
Introduction to Heap Data Structure + Priority Queue + Heapsort Tutorial
Kunal Kushwaha provides a very intuitive, step-by-step walkthrough of inserting an element and rebalancing the heap upwards.
Watch from 21:34 to 28:12. Follow along as he inserts the value 5 into a min-heap and repeatedly swaps it with its parent until the heap property is restored.
Now that you've seen the logic, let's look at a clean Java implementation.
6.11 Binary Heap Implementation
The article 'Binary Heap Implementation' from Runestone Academy provides a clear, well-structured Java implementation of a min-heap. We will focus on the insertion logic.
Read the section titled 'The insert Method' (which includes Listings 6.11.5, 6.11.6, and 6.11.8). Pay attention to the percolateUp method, which contains the core logic for bubbling an element up the heap.
3.2 extractMin and percolateDown
Extracting the minimum element from a min-heap always means removing the root.
- Save the root: The root (
array[0]) is the minimum element. Store it to return later. - Move last element to root: Take the last element in the heap and place it at the root position. Then, shrink the heap size by one. This is a clever trick to maintain the complete tree structure.
- Fix the heap property: The new root is likely larger than one or both of its children, violating the min-heap property. To fix this, we "percolate down" (or "bubble down"). We compare the node with its children, find the smaller of the two children, and if that child is smaller than the current node, we swap them. We repeat this process, moving the element down the tree until it's in its correct position.
This operation also has a time complexity of .
Let's watch a dry run of this downheap process.
Introduction to Heap Data Structure + Priority Queue + Heapsort Tutorial
Kunal Kushwaha also has a great visualization for the removal process.
Watch from 28:12 to 31:54. Observe how removing the root is handled by replacing it with the last element and then 'sinking' it down to its correct position by swapping with the smaller child.
Now, let's examine the corresponding Java code.
6.11 Binary Heap Implementation
Let's return to the Runestone Academy article for the implementation of the delete operation.
Read the section covering the delete method (which includes Listings 6.11.10 and 6.11.11). The percolateDown method is the critical piece here. Notice how it finds the smaller child before deciding whether to swap.
Test your understanding!
In the percolateDown logic for a min-heap, you compare the parent with its two children and swap it with the smaller of the two (if a swap is needed).
If you were implementing percolateDown for a max-heap, what would you swap the parent with?
Show answer
For a max-heap, you would swap the parent with the larger of its two children (if that child is larger than the parent). The goal is always to move the "out-of-place" element down while moving the more "extreme" (larger in a max-heap, smaller in a min-heap) element up.
3.3 Implementing a Max-Heap
Implementing a max-heap is straightforward once you have a min-heap. You simply flip every comparison:
- In
percolateUp, you swap ifchild > parent. - In
percolateDown, you swap with the larger child ifchild > parent.
4. Complete Heap Implementation in Java
Now let's put all the pieces together into a single, generic Heap class. The following resource provides a full code-along that creates a generic heap implementation from scratch, which is excellent practice for your interview preparation.
Introduction to Heap Data Structure + Priority Queue + Heapsort Tutorial
Kunal Kushwaha's live coding session is a great way to see a full implementation come together. He builds a generic min-heap class using an ArrayList.
Watch from 35:08 to 50:32. You don't need to code along right now, but observe how he structures the class with helper methods for parent/child indices, swap, upheap, and downheap. This demonstrates how the concepts we've discussed translate into a complete, working data structure.
Conclusion
Great job! You've just learned how to implement one of the most useful data structures in computer science. By representing a complete binary tree with an array and using clever "percolating" algorithms, we can build a highly efficient structure for priority-based problems.
Key Takeaways:
- A Binary Heap is a complete binary tree that satisfies the min-heap or max-heap property.
- It can be efficiently implemented using an array by calculating parent/child relationships with index arithmetic:
parent = (i-1)/2,leftChild = 2*i+1,rightChild = 2*i+2. - Insertion involves adding an element to the end of the array and calling
percolateUpto restore the heap property. Complexity: . - Extraction (of min/max) involves replacing the root with the last element, shrinking the array, and calling
percolateDownon the new root. Complexity: . - A max-heap implementation is identical to a min-heap, with all comparisons reversed.
Preview of the Next Lesson:
We learned how to build a heap by inserting elements one by one. But what if you are given a whole collection of items at once? In the next lesson, we will explore a more efficient method to build a heap from an unordered array in linear time. This "heapify" algorithm is a classic and powerful technique. After that, we'll be ready to implement Heap Sort