Heap Data Structure - Interview Cake

Download as pdf or txt
Download as pdf or txt
You are on page 1of 15

Interview Cake

5 2

16 19 36 7

25 42

Heap
Data Structure (/data-structures-reference)

Other names:
min heap, max heap

Quick reference
A binary heap is a binary tree where the smallest value is Worst Case
always at the top.
get min O(1)

remove min O(lg(n))


1
insert O(lg(n))
5 2
heapify O(n)
16 19 36 7
space O(n)
25 42

A min-heap has the smallest value at the top. A max-heap has the largest value at the top. We'll describe min-
heaps here, but the implementation for max-heaps is nearly identical.
Strengths:
Quickly access the smallest item. Binary heaps allow you to grab the smallest item (the
root) in O(1) time, while keeping other operations relatively cheap (O(lg(n)) time).

Space e cient. Binary heaps are usually implemented with arrays, saving the overhead
cost of storing pointers to child nodes.

Weaknesses
Limited interface. Binary heaps only provide easy access to the smallest item. Finding
other items in the heap takes O(n) time, since we have to iterate through all the nodes.

Uses
Priority queues (/concept/priority-queue) are often implemented using heaps. Items are
enqueued by adding them to the heap, and the highest-priority item can quickly be grabbed
from the top.
One way to e ciently sort an array of items (/concept/heapsort) is to make a heap out of
them and then remove items one at a time—in sorted order.

Implementation
Heaps are implemented as complete binary trees (/concept/complete-binary-tree).

In a complete binary tree:

each level is lled up before another level is added, and


the bottom tier is lled in from left to right.

As we'll see, this allows us to e ciently store our heap as an array.

In a heap, every node is smaller than its children.


1
>1

5 2

16 19 36 7

25 42

5 2
>5

16 19 36 7

25 42

5 2
>2

16 19 36 7

25 42

5 2

16 19 36 7
> 16

25 42
Inserting a new item

10 5

11 12 6 8

15 20 13

Add the item to the bottom of the tree.

10 5

11 12 6 8

15 20 13 7

Compare the item with its parent. If the new item is smaller, swap the two.
3

10 5

11 12 6 8

15 20 13 7

10 5

11 7 6 8

15 20 13 12

Continue comparing and swapping, allowing the new item to "bubble up" until the it's larger
than its parent.

10 5

11 7 6 8

15 20 13 12

7 5

11 10 6 8

15 20 13 12

Because our heap is built on a complete binary tree, we know it's also balanced. Which means the
height of the tree is lg n. So we'll do at most lg n of these swaps, giving us a total time cost of
O(lg n).
Removing the smallest item
Easy—it's right there at the top:

7 5

11 10 6 8

15 20 13 12

Now, we have to shuf e some things around to make this a valid heap again.

Take the bottom level's right-most item and move it to the top, to ll in the hole.

7 5

11 10 6 8

15 20 13 12

Compare the item with its children.


12

7 5

11 10 6 8

15 20 13

If it's larger than either child, swap the item with the smaller of the two children.

12

7 5

11 10 6 8

15 20 13

7 12

11 10 6 8

15 20 13

Continue comparing and swapping, allowing the item to "bubble down" until it's smaller
than its children.
5

7 12

11 10 6 8

15 20 13

7 12

11 10 6 8

15 20 13

7 6

11 10 12 8

15 20 13

As with inserting (above), we'll do at most lg n of these swaps, giving us a total time cost of
O(lg n).

Heaps are built on arrays


Complete trees and heaps are often stored as arrays, one node after the other, like this:
0
8
1 2
3 2
3 4 5 6
7 9 1 4

8 3 2 7 9 1 4
0 1 2 3 4 5 6

Using an array to store a complete binary tree is very ef cient. Since there are no gaps in
complete trees, there are no unused slots in the array. And, inserting a new item in the bottom
right part of the tree just means appending to the array.

But how do we traverse the tree when it's an array? How do we go from a node to its left and
right children? With a bit of clever indexing! See if you can come up with the formulas for a
node's left child, right child, and parent. Then, check your answer.↴

Heapify: Transform an Array Into a Heap


Say we want to make a heap out of the items in an array.

We could create a new empty heap and add in the items from the array one at a time. If the array
has n elements, then this takes O(n ∗ lg(n)).

It turns out that there's a more e cient way to transform an array into a heap.

We'll take our input array and treat it like the nodes in a complete binary tree, just like we did
above:
0
8
1 2
3 2
3 4 5 6
7 9 1 4

8 3 2 7 9 1 4
0 1 2 3 4 5 6

To transform the tree into a valid heap, we'll compare each node to its children and move nodes
around so that parent nodes are always smaller than their children.

This causes larger nodes to move lower in the tree, "bubbling down" to allow smaller values to
reach the top.

Look familiar? This is the same bubbling down we were doing to remove items from the heap!

We'll work from the leaf-nodes at the bottom upwards. To start off, let's look at the leaves.

The leaf nodes don't have any children, so they don't need to move down at all. Great.

3 2

7 9 1 4

8 3 2 7 9 1 4

Let's look at the nodes in the next level:


8

3 2

7 9 1 4

8 3 2 7 9 1 4

We'll start with the left node (3) and its children:

3 2

7 9 1 4

8 3 2 7 9 1 4

Since 3 is smaller than both 7 and 9, it's already in the right spot.

But, looking at the right node (2) and its children, since 1 is smaller than 2, we'll swap them.

3 2

7 9 1 4

8 3 2 7 9 1 4

3 1

7 9 2 4

8 3 1 7 9 2 4
Notice how we've got two small valid min-heaps. We're getting close!

3 1

7 9 2 4

8 3 1 7 9 2 4

Moving up, we've got an 8 at the root.

3 1

7 9 2 4

8 3 1 7 9 2 4

Since 8 is larger than 1, 8 bubbles down, swapping places with the smaller child: 1.

3 1

7 9 2 4

8 3 1 7 9 2 4

3 8

7 9 2 4

1 3 8 7 9 2 4
Then, we need to compare 8 to its two children—2 and 4. Since 8 is bigger than both of them, we
swap with the smaller child, which is 2.

3 8

7 9 2 4

1 3 8 7 9 2 4

3 2

7 9 8 4

1 3 2 7 9 8 4

At this point, we've transformed the input tree into a valid min heap. Nice!

Heapify complexity
What's the time complexity of heapify'ing an array?

It's tempting to say it's O(n ∗ lg(n)). After all, we have to examine all n nodes, and a node might
bubble down O(lg(n)) levels.

That's an overestimate of the amount of work though. All of the leaf nodes at the bottom of the
tree won't have to move down at all. And the parents of those nodes will only move down once. In
fact, there's only one node that might move down O(lg(n)) times: the root node.
Since binary heaps are based on complete binary trees, (/concept/complete-binary-tree) there
will be n/2 nodes in the bottom level, n/4 nodes in the second-to-last level, etc. Each time we go
up a level we cut the number of nodes in half.

So, we'll move n/2 nodes on the bottom level 0 times. The n/4 nodes one level up move at most 1
time. Then, n/8 nodes move at most 2 times. And so on, until we get to the root node, which
moves lg(n) times.

Adding this all up, we've got:

n n n n
0∗ 2
+1∗ 4
+2∗ 8
+3∗ 16
+…

Alternatively, this can be expressed as a summation:

i
n ∗ ∑ 2i+1

The sum is a geometric series that converges to 1/2. (Take our word for it—the arithmetic to
prove this gets a bit hairy.) Then, multiplying by n, we have n/2. That's O(n).

Interview coming up?


Get the free 7-day email crash course. You'll learn how to think algorithmically, so you can
break down tricky coding interview questions.

No prior computer science training necessary—we'll get you up to speed quickly, skipping
all the overly academic stu .
No spam. One-click unsubscribe whenever.

[email protected] Get the rst day now!

What's next?
If you're ready to start applying these concepts to some problems, check out our mock coding
interview questions (/next).

They mimic a real interview by o ering hints when you're stuck or you're missing an
optimization.

Try some questions now 

Want more coding interview help?

Check out interviewcake.com for more advice, guides, and practice questions.

You might also like