在阵列上的Downheap给出了错误的输出

时间:2017-03-01 04:10:16

标签: java sorting heap heapsort

我正在编写一个执行堆排序的程序。当我尝试执行removeMin函数和一个下降时,似乎我总是得到不正确的输出。

例如,如果我按此顺序输入10个整数:

3, 6, 8, 3, 89, 35, 7, 9, 1, 4

我希望

1, 3, 3, 4, 6, 7, 8, 9, 35, 89 

但我明白了:

1, 3, 3, 4, 6, 7, 8, 9, 35, 35

这是我的代码堆代码:

public class heapsort {

private Integer[] myHeap;
private int size;
private int maxSize;

public heapsort (int x){
    myHeap = new Integer[x+1];
    maxSize=x;
    size=0;
}

public void min(){
    if (isEmpty())
        System.out.print("Is empty");
    else
        System.out.println(myHeap[0]);
}

public boolean isEmpty(){
    return (size==0);
}

public int size(){
    return size;
}

public void insert(int x){
    if (size==maxSize)
        System.out.println("Heap is full");
    else{
        size++;
        myHeap[size] = x;
        upheap(size);
    }
}

public void upheap(int x){
    int temp;
    if (x>1){
        if (myHeap[x]<myHeap[x/2]){
            temp = myHeap[x];
            myHeap[x]=myHeap[x/2];
            myHeap[x/2]=temp;
            upheap(x/2);
        }
    }   
}

public void removeMin(){
    int temp;
    temp = myHeap[1];
    myHeap[1]=myHeap[size-1];
    size--;
    if (size>1){
        downheap(1);
    }
    System.out.println(temp);
}

public void downheap(int x){
    int temp;

    int temp, minIndex, left=2*x, right=2*x+1;

    if (right>=size){
        if (left>=size)
            return;
        else
            minIndex=left;
    }

    else{
        if (myHeap[left] <= myHeap[right])
            minIndex = left;
        else
            minIndex = right;
    }

    if (myHeap[x] > myHeap[minIndex]){
        temp = myHeap[minIndex];
        myHeap[minIndex]=myHeap[x];
        myHeap[x]=temp;
        downheap(minIndex);
    }
}

接下来是我的主程序:

public static void main (String[] args){
    int i=0;
    Scanner input = new Scanner(System.in);
    System.out.println("Enter array size: ");
    int n = input.nextInt();

    heapsort myArray = new heapsort(n);
        System.out.println("Please input integers");
    for (i=1; i<=n; i++){
        myArray.insert(input.nextInt());
    }

    while (!myArray.isEmpty()){
        myArray.removeMin();
    }
}
}

1 个答案:

答案 0 :(得分:0)

在我看来,从几次运行中你的排序会丢弃一个元素,然后打印最后一个元素两次。如果我输入的数组大小为2,数字3和4(或4和3),我得到

3
3

我认为这是一个足够简单的案例,您应该能够考虑removeMin方法中发生的事情。你的数组是[null, 3, 4](因为你从不使用第0个元素),大小是2. temp会是什么?您要将哪个数组元素复制到myHeap[1]?什么是新size?是downheap(1)是否会被召唤?请记住,索引是从0开始的。我故意把答案留给你,我相信你会弄清楚并且能够解决你的错误。

PS我修复了我认为的错误。现在,如果我输入的数组大小为3,数字为1 2 3,那么我得到

1
3
2

所以要么我错了,要么还有一个bug。希望你能搞清楚。培养你的调试技巧很好,这不是你最后一次需要它们。

PPS您的min方法错误,因为您没有使用它并不重要。并且您在temp中声明downheap()两次(您可能已经发现它已经无法编译)。

编辑:警告:剧透

Stephen O'C,我相信你现在已经发现了你的错误,所以我不会通过确认你的知识对你的学习造成任何伤害,而且其他人一起阅读可能也有兴趣知道。所以这里是我发现的错误以及如何解决它们。

第一个错误发生在removeMin()方法中。这一行

    myHeap[1] = myHeap[size - 1];

应该是

    myHeap[1] = myHeap[size];

我们希望将堆的最后一个元素移到顶部。由于元素在索引1 throgh size中,我们不应该从size中减去1(如果我们将数组用作从0开始,size - 1就是正确的。这个错误导致了任何元素最后在堆中结束 - 通常是更大的元素之一。

使用此修复程序,代码似乎可以正常工作,但现在然后在排序的输出中交换两个元素。错误出现在这两行downheap()

    if (right >= size) {
        if (left >= size)
            return;

如果rightleft分别等于size,它们仍然指向堆的元素,所以在这种情况下我们需要进行筛选操作而不能在这一点上回归。这是一个非常类似于第一个的错误。修复是使用严格大于运算符:

    if (right > size) {
        if (left > size)

通过此修复,我无法发现任何错误。