Skip to Content
Course content

175: Implementing a Min-Heap

Click on the "Edit" button in the top corner of the screen to edit your slide content.

Think about a hospital's emergency room triage. Patients don't just get seen in the order they arrive; they get seen based on the severity of their condition. If someone comes in with a minor scrape, they wait. If someone comes in with a heart attack, they jump to the front of the line immediately. A Min-Heap is essentially a triage system for data. It ensures that the "most urgent" (the smallest) value is always sitting right at the top, ready to be grabbed, regardless of when it was added to the pile.

Here is how that maps to the logic we're about to write:

  • The Patient: This is the value you're inserting into the heap.
  • Triage Priority: In a Min-Heap, the smaller the number, the higher the priority.
  • The Waiting Room: We use an array to represent a binary tree. It's a bit of a mental leap, but it's much faster than creating actual "Node" objects with left and right pointers.
  • Moving Up the Line: When a critical patient arrives, they "bubble up" through the queue until they are in the right spot relative to others.
  • Filling the Gap: When the doctor takes the most urgent patient, someone else has to step up, and we "bubble down" to make sure the next most urgent person is now at the front.

Flattening a Tree into an Array

I know it sounds weird to store a tree in a flat array, but this is the "secret sauce" of heaps. Since a heap is always a complete binary tree, we don't need pointers. We can use simple math to find relatives. If you're at index i:

  • Your left child is at 2i + 1.
  • Your right child is at 2i + 2.
  • Your parent is at Math.floor((i - 1) / 2).

I've spent hours debugging off-by-one errors in the past because I forgot these formulas. Memorize them, or keep them on a sticky note; they are the foundation of the whole structure.

Keeping the Peace: Bubbling Up and Down

The core of a Min-Heap is maintaining the "Heap Property": every parent must be smaller than its children. When we break that rule—either by adding a new element or removing the root—we have to fix it.

class MinHeap {
    constructor() {
        this.heap = [];
    }

    insert(val) {
        this.heap.push(val);
        this.bubbleUp(this.heap.length - 1);
    }

    bubbleUp(index) {
        while (index > 0) {
            let parentIndex = Math.floor((index - 1) / 2);
            if (this.heap[parentIndex] <= this.heap[index]) break;
            
            // Swap parent and child
            [this.heap[parentIndex], this.heap[index]] = [this.heap[index], this.heap[parentIndex]];
            index = parentIndex;
        }
    }

    extractMin() {
        if (this.heap.length === 0) return null;
        if (this.heap.length === 1) return this.heap.pop();

        const min = this.heap[0];
        // Move the last element to the top and bubble it down
        this.heap[0] = this.heap.pop();
        this.bubbleDown(0);
        return min;
    }

    bubbleDown(index) {
        while (true) {
            let left = 2 * index + 1;
            let right = 2 * index + 2;
            let smallest = index;

            if (left < this.heap.length && this.heap[left] < this.heap[smallest]) {
                smallest = left;
            }
            if (right < this.heap.length && this.heap[right] < this.heap[smallest]) {
                smallest = right;
            }

            if (smallest === index) break;

            [this.heap[index], this.heap[smallest]] = [this.heap[smallest], this.heap[index]];
            index = smallest;
        }
    }
}

Notice in extractMin how I don't just shift the whole array. Shifting an array is an O(n) operation, which would kill the performance of our heap. Instead, I take the very last element—the one that's least likely to be the minimum—and throw it at the top. It'll probably be way too large for that spot, but bubbleDown will efficiently sink it to its rightful place in O(log n) time.




📋 Practical Task

Build a Priority-Based Task Scheduler

You need to build a TaskScheduler class that uses the MinHeap implementation from the lesson. Instead of just storing numbers, your heap should store "Task" objects. Each task has a priority (lower number = higher priority) and a description.

Requirements:

  • Modify the MinHeap logic to compare the priority property of the objects rather than the objects themselves.
  • Implement a addTask(description, priority) method.
  • Implement a processNextTask() method that extracts and returns the task with the highest priority (the lowest priority number).
  • Test your scheduler by adding tasks in this order:
    • "Fix CSS bug" (Priority 3)
    • "Server crash" (Priority 1)
    • "Update documentation" (Priority 5)
    • "Security patch" (Priority 2)
  • Verify that calling processNextTask() four times returns the tasks in the order: Server crash, Security patch, Fix CSS bug, Update documentation.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.