我正在尝试以下代码进行堆排序,它给出了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
方法的第三行并取消注释第四行。请帮助理解这种魔力。
答案 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 / 2
中l = 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
谓词的两个子句与&&
运算符连接,因此根据短路规则,第二个子句中的表达式甚至不会被评估,从而使您无法访问数组绑定索引。因此,您不会收到任何错误。