Java 最大堆未按预期工作

Java 最大堆未按预期工作,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

我的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.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@MonaJalal
size
变量不会增加数组的大小。它只是记录你在里面的东西的数量。但是数组是零相对的。因此,如果您将大小从0增加到1,然后在位置1插入,那么您将新元素放置在一个实际上不存在的插槽中(在逻辑意义上)。您需要插入,然后递增。您的意思是我应该将其更改为
size++;堆[size]=n?堆[size]=n;大小++?或
堆[size++]=n?它们是等价的,因为我认为应该首先增加数组的大小,然后在最后分配的插槽中插入元素@埃里克。Hagstrom@MonaJalal
size
变量不会增加数组的大小。它只是记录你在里面的东西的数量。但是数组是零相对的。因此,如果您将大小从0增加到1,然后在位置1插入,那么您将新元素放置在一个实际上不存在的插槽中(在逻辑意义上)。您需要先插入,然后递增。@MonaJalal:发生异常是因为您正在索引数组的末尾。堆中有8项。堆数组有9个位置(0到8)。但是当你到达第四个节点时,它会尝试看正确的子节点:(i*2)+1,也就是9。繁荣您的
print
方法必须检查其计算的索引是否小于大小。@MonaJalal:发生异常是因为您正在索引数组的末尾。堆中有8项。堆数组有9个位置(0到8)。但是当你到达第四个节点时,它会尝试看正确的子节点:(i*2)+1,也就是9。繁荣您的
print
方法必须检查其计算的索引是否小于大小。