0

For the below program:

public class MinHeap<T extends Comparable<? super T>>
implements HeapInterface<T> {

private T[] backingArray;
private int size;
// Do not add any more instance variables

/**
 * Creates a Heap.
 */
public MinHeap() {
    backingArray = (T[]) new Comparable[STARTING_SIZE];
    size = 0;
}

@Override
public void add(T item) {
    if (item == null) {
        throw new IllegalArgumentException("Item was null.");
    }
    if (size + 1 >= backingArray.length) {
        resize();
    }
    backingArray[size + 1] = item;
    int i = size + 1;
    while (i > 1 && backingArray[i].compareTo(backingArray[i / 2]) <= 0) {
        swap(backingArray[i], backingArray[i / 2], i, i / 2);
        i = i / 2;
    }
    size++;
}

private void resize() {
    T[] backingArrayTemp = backingArray;
    backingArray = (T[]) new Comparable[backingArrayTemp.length * 2];
    for (int i = 1; i < size + 1; i++) {
        backingArray[i] = backingArrayTemp[i];
    }
}

private void swap(T item1, T item2, int i, int parent) {
   backingArray[parent] = item1;
   backingArray[i] = item2;
}
@Override
public T remove() {
    if (isEmpty()) {
        throw new NoSuchElementException("Heap is empty.");
    }
    T temp = backingArray[1];
    backingArray[1] = backingArray[size + 1];
    size--;
    heapify(1);
    return temp;
}

private void heapify(int i) {
    int left = 2*i;
    int right = 2*i + 1;
    int min = i;
    if (left < size && backingArray[left].compareTo(backingArray[min])
            < 0) {
        min = left;
    }
    if (right < size
            && backingArray[right].compareTo(backingArray[min]) < 0) {
        min = right;
    }
    if (min != i) {
        swap(backingArray[i], backingArray[min], i, min);
        heapify(min);
    }
}
@Override
public boolean isEmpty() {
    return size == 0;
}

@Override
public int size() {
    return size;
}

@Override
public void clear() {
    size = 0;
    backingArray = (T[]) new Comparable[STARTING_SIZE];
}

We start indexing at i = 1. My add method works fine, and I've tried changing from backingArray[1] = backingArray[size + 1]; to backingArray[1] = backingArray[size] in the remove method, but that doesn't seem right and also didn't work. It got rid of the null pointer but didn't pass all my tests. I'm getting null pointers at

backingArray[left].compareTo(backingArray[min]) < 0)

because backingArray[min] is null.

Stack trace

java.lang.NullPointerException
at java.lang.Integer.compareTo(Integer.java:1216)
at java.lang.Integer.compareTo(Integer.java:52)
at MinHeap.heapify(MinHeap.java:68)
at MinHeap.remove(MinHeap.java:60)
rajuGT
  • 6,224
  • 2
  • 26
  • 44

2 Answers2

0

I can't really test this, right now, but I think the main problem is in the resize() method. When you create the temporary array to hold the data

T[] backingArrayTemp = backingArray;

you actually tell the new array to point to the same address in the memory as the original backingArray. Then you reallocate backingArray and also the temp array, since they point to the same place in memory. Then, of course, all the elements will not be initialized and the bеhaviour will not be as expected.

The correct way to do this is to create a "new" array and then copy the values:

T[] backingArrayTemp = new T[backingArray.length];
for(int i = 0; i < backingArray.length; ++i)
    backingArrayTemp[i] = new T(backingArray[i]);

Where each element is copied with a constructor to avoid similar issues.

About heapify() - I don't know how exactly you will use that min heap, but I guess you will always put the elements one at a time. If you ever need to create the heap from a random array you will need a more complex routine that goes through the entire heap. I can provide you with some more information, if interested.

M.Paunov
  • 1,737
  • 1
  • 15
  • 19
  • I'm adding elements one at a time. I'm sure something is wrong with the heapify method. My tests for resize work, but I'm mainly concerned with heapify. –  Sep 20 '15 at 21:30
  • Ok then. Why in the remove() method you use "size + 1" in the following line: backingArray[1] = backingArray[size + 1]; Shouldn't it be size - 1? – M.Paunov Sep 20 '15 at 22:40
  • That was because we started the array indices at 1. –  Sep 26 '15 at 01:10
0

The problem was I didn't set backingArray[size] = null.