Java 实现Heapify以删除MinHeap中的最小值时出现空指针异常

Java 实现Heapify以删除MinHeap中的最小值时出现空指针异常,java,nullpointerexception,heap,Java,Nullpointerexception,Heap,对于以下程序: 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() { ba

对于以下程序:

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];
}
因为
backingArray[min]
为空

堆栈跟踪

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)

我现在无法真正测试这个,但我认为主要问题在于
resize()
方法。创建临时数组以保存数据时

T[] backingArrayTemp = backingArray;
实际上,您告诉新数组指向内存中与原始backingArray相同的地址。然后重新分配
backingArray
和临时数组,因为它们指向内存中的同一位置。然后,当然,所有元素都不会被初始化,行为也不会像预期的那样

正确的方法是创建一个“新”数组,然后复制值:

T[] backingArrayTemp = new T[backingArray.length];
for(int i = 0; i < backingArray.length; ++i)
    backingArrayTemp[i] = new T(backingArray[i]);
T[]backingArray=new T[backingArray.length];
对于(int i=0;i
使用构造函数复制每个元素以避免类似问题


关于
heapify()
-我不知道您将如何准确地使用最小堆,但我想您总是会一次放置一个元素。如果需要从随机数组创建堆,则需要一个更复杂的例程来遍历整个堆。如果有兴趣,我可以向您提供更多信息。

问题是我没有设置backingArray[size]=null

请提供stacktrace。刚刚添加了跟踪。您总是使用
i=1
,但是第一个元素的索引是
0
-可能是这样吗?不,第一个元素应该是1。这是我们实施它的方式。这是一个小细节。你能解释一下
heapify()
的用途吗,特别是
remove()
中的
heapify(1)
?我一次添加一个元素。我肯定heapify方法有问题。我的测试可以调整大小,但我主要关心的是heapify。好吧。为什么在remove()方法中在以下行中使用“size+1”:backingArray[1]=backingArray[size+1];它不应该是大小-1吗?那是因为我们从1开始数组索引。
T[] backingArrayTemp = new T[backingArray.length];
for(int i = 0; i < backingArray.length; ++i)
    backingArrayTemp[i] = new T(backingArray[i]);