Java 最大堆未按预期工作
我的Max Heap Java代码未按预期工作。当我从堆中移除时,它也没有返回最大值90Java 最大堆未按预期工作,java,algorithm,data-structures,heap,binary-heap,Java,Algorithm,Data Structures,Heap,Binary Heap,我的Max Heap Java代码未按预期工作。当我从堆中移除时,它也没有返回最大值90 /** * Created by mona on 5/25/16. */ public class Heap { private int[] heap; private int size; private int maxSize; public Heap(int maxSize) { this.maxSize=maxSize; this
/**
* Created by mona on 5/25/16.
*/
public class Heap {
private int[] heap;
private int size;
private int maxSize;
public Heap(int maxSize) {
this.maxSize=maxSize;
this.size=0;
heap=new int[this.maxSize+1];
}
private int parent(int pos) {
return pos/2;
}
private int leftChild(int pos) {
return pos*2;
}
private int rightChild(int pos) {
return pos*2 +1;
}
private boolean isLeaf(int pos) {
if (pos>=size/2 && pos<=size) {
return true;
}
return false;
}
private void swap(int pos1, int pos2) {
int tmp=heap[pos1];
heap[pos1]=heap[pos2];
heap[pos2]=tmp;
}
private void maxHeapify(int pos) {
if (!isLeaf(pos)){
if ((heap[pos] < heap[leftChild(pos)]) ||
(heap[pos] < heap[rightChild(pos)])) {
if (heap[leftChild(pos)] > heap[rightChild(pos)]) {
swap(pos , leftChild(pos));
maxHeapify(leftChild(pos));
}
else {
swap(pos , rightChild(pos));
maxHeapify(rightChild(pos));
}
}
}
}
public void maxHeap() {
for (int i=(size/2) ; i>=1 ; i--) {
maxHeapify(i);
}
}
public void insert(int n) {
heap[++size] = n;
int tmpLocation = size;
while (heap[tmpLocation] > heap[parent(tmpLocation)]){
swap(tmpLocation , parent(tmpLocation));
tmpLocation=parent(tmpLocation);
}
}
public int remove() {
int removed = heap[1];
heap[1] = heap[size-1];
maxHeapify(1);
return removed;
}
public void print() {
for (int i=1 ; i<=(size/2) ; i++) {
System.out.println("current node is: "+heap[i]+" its left child is " +
heap[i*2]+" its right child is "+heap[i*2 +1]);
}
}
public static void main(String[] args) {
Heap heap = new Heap(9);
heap.insert(8);
heap.insert(18);
heap.insert(28);
heap.insert(9);
heap.insert(12);
heap.insert(90);
heap.insert(1);
heap.insert(87);
heap.maxHeap();
heap.print();
System.out.println("Max is: "+heap.remove());
}
}
您还可以在输出的第一行中看到,它表示90的左子代是90,这是不正确的。那是什么
current node is: 90 its left child is90 its right child is 87
更新:当我将大小设置为8时,出现以下错误:
Exception in thread "main" current node is: 90 its left child is90 its right child is 87
current node is: 87 its left child is28 its right child is 18
current node is: 28 its left child is12 its right child is 9
current node is: 18 its left child is8 its right child is 1
java.lang.ArrayIndexOutOfBoundsException: 9
at Heap.print(Heap.java:86)
at Heap.main(Heap.java:104)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Process finished with exit code 1
更新:我认为如果我将插入内容更改为以下内容会有所帮助,但没有:
public void insert(int n) {
size++;
heap[size] = n;
int tmpLocation = size;
if (tmpLocation!=1) {
while (heap[tmpLocation] > heap[parent(tmpLocation)]) {
swap(tmpLocation, parent(tmpLocation));
tmpLocation = parent(tmpLocation);
}
}
}
罪魁祸首是这样的:
heap[++size] = n;
插入第一个元素时,插入位置为1,执行步骤后,每次插入后,heap[0]&heap[1]的值都相同。这就是为什么每次插入后都会看到父级和左级具有相同的值
例如,在插入第一个元素时,尝试在堆[1]处插入,并在堆[0]和堆[1]之间执行交换。结果是在堆[0]和堆[1]中得到相同的值。罪魁祸首是这一行:
heap[++size] = n;
插入第一个元素时,插入位置为1,执行步骤后,每次插入后,heap[0]&heap[1]的值都相同。这就是为什么每次插入后都会看到父级和左级具有相同的值
例如,在插入第一个元素时,尝试在堆[1]处插入,并在堆[0]和堆[1]之间执行交换。结果是在heap[0]和heap[1]中得到相同的值。在
insert
和remove
方法中,代码假定根节点位于heap[1]
。但是您的print
方法认为堆中的根节点位于heap[0]
。那会给你带来各种各样的麻烦
还要注意,您的
remove
方法不会减小大小
在insert
和remove
方法中,代码假定根节点位于堆[1]
。但是您的print
方法认为堆中的根节点位于heap[0]
。那会给你带来各种各样的麻烦
另外请注意,您的
remove
方法不会减少大小
堆中有9个节点-只有8个节点会出现类似问题吗?还是3?还是2?等等。请尝试解决您的问题,以便您可以更轻松地自己调试它,我们也更容易看到问题。我将堆大小设置为8时出错是的,这是因为索引从0开始,这意味着0…8所以您没有数字9,但有9个元素注意,插入时,堆从索引1开始,但当您打印时,您正在从索引0打印。这也许可以解释错误,也可能不能解释错误,但这只是一个开始。此外,您还应该检查之前的大小是否大于maxsizeinserting@Mona我希望通过下面的所有评论和回答,你能达到目标。你的堆中有9个节点——你有没有在8个节点上遇到类似的问题?还是3?还是2?等等。请尝试解决您的问题,以便您可以更轻松地自己调试它,我们也更容易看到问题。我将堆大小设置为8时出错是的,这是因为索引从0开始,这意味着0…8所以您没有数字9,但有9个元素注意,插入时,堆从索引1开始,但当您打印时,您正在从索引0打印。这也许可以解释错误,也可能不能解释错误,但这只是一个开始。此外,您还应该检查之前的大小是否大于maxsizeinserting@Mona我希望通过下面的所有评论和回答,你能达到目标。你是说我应该把它改成size++;堆[size]=n代码>?堆[size]=n;大小++代码>?或堆[size++]=n代码>?它们是等价的,因为我认为应该首先增加数组的大小,然后在最后分配的插槽中插入元素@埃里克。Hagstrom@MonaJalalsize
变量不会增加数组的大小。它只是记录你在里面的东西的数量。但是数组是零相对的。因此,如果您将大小从0增加到1,然后在位置1插入,那么您将新元素放置在一个实际上不存在的插槽中(在逻辑意义上)。您需要插入,然后递增。您的意思是我应该将其更改为size++;堆[size]=n代码>?堆[size]=n;大小++代码>?或堆[size++]=n代码>?它们是等价的,因为我认为应该首先增加数组的大小,然后在最后分配的插槽中插入元素@埃里克。Hagstrom@MonaJalalsize
变量不会增加数组的大小。它只是记录你在里面的东西的数量。但是数组是零相对的。因此,如果您将大小从0增加到1,然后在位置1插入,那么您将新元素放置在一个实际上不存在的插槽中(在逻辑意义上)。您需要先插入,然后递增。@MonaJalal:发生异常是因为您正在索引数组的末尾。堆中有8项。堆数组有9个位置(0到8)。但是当你到达第四个节点时,它会尝试看正确的子节点:(i*2)+1,也就是9。繁荣您的print
方法必须检查其计算的索引是否小于大小。@MonaJalal:发生异常是因为您正在索引数组的末尾。堆中有8项。堆数组有9个位置(0到8)。但是当你到达第四个节点时,它会尝试看正确的子节点:(i*2)+1,也就是9。繁荣您的print
方法必须检查其计算的索引是否小于大小。