我正在练习编写一些排序算法,并编写了以下插入排序代码:
public static void insertionSort(int[] nums) {
for (int i = 1; i < nums.length; i++) {
int idx = i;
int val = nums[idx];
while (idx > 0 && val < nums[idx - 1]) {
nums[idx--] = nums[idx - 1];
}
nums[idx] = val;
}
}
前面的代码导致索引越界异常(-1)。我对
nums[idx--] = nums[idx-1]
如何工作的理解是,nums[idx]
将被赋予 nums[idx-1]
处的值,然后 --
会将 idx
减一(我认为在变量之后使用它的全部目的是允许用户在向上或向下递增之前对当前值采取操作/执行赋值。但是,似乎一旦代码检查表达式左侧的 nums[idx-1]
,idx--
就已经发生了,导致在指针在数组末尾命中 -1 时。根据这个结果,可以肯定地说我最初的假设是递减不是该行最后执行的部分,而是我们应该假设递减将会发生首先,如果它位于变量下一次使用的左侧?
作为后续行动,有谁知道为什么要这样设置?这似乎违反直觉。
作为参考,将代码更改为以下解决了该问题,这验证了它在检查之前必须递增:
public static void insertionSort(int[] nums) {
for (int i = 1; i < nums.length; i++) {
int idx = i;
int val = nums[idx];
while (idx > 0 && val < nums[idx - 1]) {
nums[idx] = nums[idx - 1];
idx--;
}
nums[idx] = val;
}
}
每个语句多次使用
idx
,因此代码中会发生以下情况:
nums[idx]
使用 idx 的当前值进行评估。idx
然后递减(idx--).nums[idx - 1]
使用新的、递减的 idx 值进行评估。所以,如果
idx
原本是1,那么在步骤1中nums[idx--]指的是nums[1],但是nums[idx - 1]指的是nums[0 - 1],也就是nums[-1] ,导致 ArrayIndexOutOfBoundsException
。