HeapSort代码snipplet给出索引超出范围的异常

时间:2017-03-03 18:53:11

标签: java indexoutofboundsexception heapsort

我正在尝试以下代码进行堆排序,它给出了ArrayIndexOutOfBoundsException异常:

package com.Sorting;

import java.util.Arrays;

public class HeapSort {

    private static int arr[];
    private static int l,r,max,hsize;
    /**
     * @param args
     */
    public static void main(String[] args) {
        int []numbers={55,2,93,1,23,10,66,12,7,54,3};
          System.out.println(Arrays.toString(numbers));
          HeapSort(numbers);
          System.out.println(Arrays.toString(numbers));
    }

    private static void HeapSort(int myarr[]) {
        // TODO Auto-generated method stub
        arr = myarr;
         hsize = arr.length - 1;
        BuildHeap(arr);
        for(int i = hsize;i>0;i--)
        {
            swap(0,i);
            hsize--;
            SatisfyHeap(arr,0);
        }       
        }

    private static void BuildHeap(int[] arr) {
        // TODO Auto-generated method stub
        for(int i = hsize/2; i>=0;i--)
        {
            SatisfyHeap(arr, i);

        }
    }

    private static void SatisfyHeap(int[] arr, int i) {
        // TODO Auto-generated method stub
         l = 2*i;
         r = 2*i+1;
        if(l<=hsize && arr[l]>arr[i])
    //  if(arr[l]>arr[i] && l<=hsize  )
        {
            max = l;
        }
        else
            max = i;
        if(r<=hsize && arr[r]>arr[max])
        {
            max = r;
        }

        if(max!=i)
        {
            swap(i,max);
            SatisfyHeap(arr, max);
        }

    }

    private static void swap(int i, int max) {
        // TODO Auto-generated method stub
        int temp = arr[i];
        arr[i] = arr[max];
        arr[max] = temp;    
    }
}

如果我只是在if SatisfyHeap方法的SatisfyHeap语句中交换左侧和右侧使用的表达式,上面的代码不会给出任何错误。即,您可以尝试评论Sub ChkAfternoonAssignmentsV2() Dim dayToChk As Variant Dim i As Variant Dim r As Range Dim p As Variant Dim days, m, sMsg As String, n days = Array("Mon", "Tue", "Wed", "Thu", "Fri") Do dayToChk = InputBox("Which day (Mon, Tue, Wed, Thu, Fri) " & _ "would you like to check afternoon assignments?") If Len(dayToChk) = 0 Then Exit Sub 'exit if nothing entered If IsError(Application.Match(dayToChk, days, 0)) Then MsgBox dayToChk & " is not in the expected format.", vbExclamation Else Set r = ActiveSheet.Range(dayToChk & "Aft_MA_Slots") End If Loop While r Is Nothing 'skipping the wscript messagebox code... For Each i In Sheets("Control").Range("MA_List") If i <> "OOO" Then n = WorksheetFunction.CountIf(r, i) If n < 1 Then sMsg = sMsg & vbLf & i & " is not assigned" ElseIf n > 1 Then sMsg = sMsg & vbLf & i & " is assigned more than once." & _ " Did you really mean to do that?" End If End If Next i If sMsg <> "" Then MsgBox "Some issues were found:" & sMsg, vbExclamation End If End Sub 方法的第三行并取消注释第四行。请帮助理解这种魔力。

2 个答案:

答案 0 :(得分:0)

简短回答

魔法被称为"short-circuit evaluation",它是针对这样的情况特别设计的。

更长的答案

在Java和许多其他语言中合乎逻辑地编码

if (condition1 && condition2) { 
    do something 
}

相当于

if (condition1) {
    if (condition2) { 
        do something 
    }
}

等同于&#34;这里我的意思是如果condition2是要计算的东西,如果condition1碰巧是false则不会计算。从布尔逻辑的角度来看,这也是正确的。这个技巧在两个方面很有用。首先,它通过跳过评估calculation2来提高性能。其次,它适用于你的condition1是一个&#34;保护条件&#34;为condition2

另一个例子是函数isEmptyString,它由许多Java开发人员以下列方式实现

public static boolean isEmptyString(String s) {
    return (string == null) || (string.length() == 0);
}

如果没有短路逻辑,如果NullPointerException恰好为空,则此表达式将引发s

您的具体案例(为什么ArrayIndexOutOfBoundsException?)

你的问题的另一点可能是&#34;如果有ArrayIndexOutOfBoundsException怎么回事?&#34;。要回答这个问题,考虑第一个元素实际上是堆中最大元素的情况,我们应该将它向下移动到树的最后一层。此向下移动由您的SatisfyHeap实施。所以现在假设我们做了最后一次交换,将最大元素移到了底部。现在,当max被更改后,我们将再进行一次递归调用,并在该调用i > arr.length / 2l = 2*i > arr.length,因此发生异常。

请注意,除非您预先分配arr大于实际堆大小,否则独立于hsize存储arr.length是一个坏主意代码更难理解。

答案 1 :(得分:0)

以下为您提供错误

if(arr[l]>arr[i] && l<=hsize )

因为l大于数组的大小,并且您试图通过传递超出数组范围的l来获取数组元素。

以下为您效劳

if(l<=hsize && arr[l]>arr[i])

因为在if条件下,首先评估的是表达式l<=hsize。由于l大于hsize,因此表达式的计算结果为false。由于if谓词的两个子句与&&运算符连接,因此根据短路规则,第二个子句中的表达式甚至不会被评估,从而使您无法访问数组绑定索引。因此,您不会收到任何错误。