You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

插入排序代码中++/--运算符的行为疑惑与问题求解

插入排序代码中的索引越界问题与后缀自减运算符解析

问题重现

最初编写的插入排序代码如下,运行时触发了索引越界异常(索引为-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];
        }
        nums[idx] = val;
    }
}

原本认为nums[idx--] = nums[idx - 1]的逻辑是:先把nums[idx-1]的值赋给nums[idx],再将idx减1(后缀自减应该先使用当前值再自减)。但实际运行中,访问右侧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;
    }
}

问题根源

你的初始假设部分错误:后缀自减运算符确实是先使用变量当前值,再执行自减操作,但问题出在Java赋值表达式的求值顺序——赋值语句是先计算左侧操作数,再计算右侧操作数,这和直觉认知的“先右后左”正好相反。

以错误代码中的nums[idx--] = nums[idx - 1]为例,当idx=1时:

  1. 先处理左侧操作数nums[idx--]:后缀自减先以当前idx值(1)作为数组下标,随后将idx自减为0;
  2. 再处理右侧操作数nums[idx-1]:此时idx已经是0,idx-1等于-1,访问nums[-1]直接触发索引越界。

为什么这样设计?

Java语言规范规定,表达式的求值顺序总体为从左到右,这是为了保证代码执行的确定性,避免因运算符优先级、结合性不同导致的歧义。虽然赋值运算符是右结合(比如a = b = c等价于a = (b = c)),但单个赋值语句的操作数求值顺序依然是左到右,这一点容易和直觉混淆,也是很多开发者踩坑的点。

内容的提问来源于stack exchange,提问作者wu650

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 19:13:26