A Heap/Binary Heap is a data structure that takes the form of Binary Tree. Heaps are commonly used to implement priority queues (check out the PriorityQueue class in Java). Priority queues are great ways to identify the highest (or lowest) priority items in a collection.

A **Max Heap** is a binary tree data structure in which the root node is the largest/maximum in the tree. This means the root node will be >= to all others. As seen the example below, all objects in our max heap implement the Comparable interface.

### Implementing a Max Heap using an Array

The most common (and generally very efficient) way to implement a max heap is by using an array. There are 4 major methods for implementing a max heap. These include `add()`

, `remove()`

, `siftUp()`

, and `siftDown()`

which are explained below.

#### The add() Method

When objects are first added to the heap they are initially added to the end of the heap. When using a traditional binary tree structure objects are added to the tree from top to bottom then left to right. When using an array, as we are in this example, objects are added to the end of the array. The final location in the tree or array depends on how the object compares to the others. Since the the object is initially inserted at the end of the array, we use the `siftUp()`

method to move it to its new location.

#### The siftUp() Method

The `siftUp()`

method is used to move a newly inserted object from the last position in the array to its final location. It works by comparing the newly inserted object to its parent. Remember, we are using an array here to simulate a tree data structure. To find and object’s parent within the array we can use the formula `parentIndex = childIndex/2`

.

Since we are building a max heap, if the child object is larger than the parent, we swap the two objects within the array. We continue doing this until the child object is no longer larger than the parent, or the child becomes the largest in the heap (located at the front of the array).

#### The remove() Method

Removing a node from the max heap will remove (and return) its largest object. The `remove()`

method removes the root object (or first object in the array). This root object is immediately replaced with the last object in the heap.

Most likely, this new root object is no longer the largest in the heap. This newly added root object is moved to its final location using the `siftDown()`

method, which is explained below.

#### The siftDown() Method

The `siftDown()`

method is used to move the newly added root object (or first object in the array) to its correct position. It works by comparing the root object to its children. Remember, we are using an array to simulate a tree data structure. To find an object’s children within the array we can use the formula `leftChild = 2 * nodeIndex + 1`

and `rightChild = 2 * nodeIndex + 2`

.

Because we are building a max heap, if the parent object is smaller than either of its children, the parent object is swapped with the larger of its children. We continue these compare and swap steps until the parent object is no longer smaller than its children, or the original root object becomes the smallest in the heap (located at the end of the array).

#### The Code

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
package com.bigdatums.interview; import java.util.ArrayList; import java.util.NoSuchElementException; public class MaxHeapArray<T extends Comparable<T>> { private ArrayList<T> items = new ArrayList<T>(); public void insert(T item) { items.add(item); siftUp(); } private void siftUp() { int k = items.size() - 1; while(k > 0) { int p = (k - 1) / 2; T child = items.get(k); T parent = items.get(p); if (child.compareTo(parent) > 0) { //swap items.set(k, parent); items.set(p, child); //adjust k k = p; } else { break; } } } private void siftDown() { int k = 0; int left = 1; while(left < items.size()) { int max = left; int right = left + 1; if(right < items.size()) { if(items.get(right).compareTo(items.get(left)) > 0) { max = right; } } T parent = items.get(k); T child = items.get(max); if(parent.compareTo(child) < 0) { //swap items.set(k, child); items.set(max, parent); k = max; left = 2*k+1; } else { break; } } } public T remove() throws NoSuchElementException { if(items.size() == 0) { throw new NoSuchElementException(); } else if (items.size() == 1) { return items.remove(0); } T tmp = items.get(0); items.set(0, items.remove(items.size()-1)); siftDown(); return tmp; } } |