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]);