
本文详解 Merge Sort 实现中因循环范围与索引计算错误导致的 ArrayIndexOutOfBoundsException,通过分析典型错误代码,指出 i 超出子数组边界、误用全局长度遍历局部子数组等核心问题,并提供正确划分左右子数组的规范写法。
本文详解 merge sort 实现中因循环范围与索引计算错误导致的 `arrayindexoutofboundsexception`,通过分析典型错误代码,指出 `i` 超出子数组边界、误用全局长度遍历局部子数组等核心问题,并提供正确划分左右子数组的规范写法。
在实现归并排序(Merge Sort)的 merge 过程时,一个常见却隐蔽的错误是:用原数组长度控制循环,却将该循环变量直接用于索引大小受限的临时子数组。这正是提问者代码中抛出 ArrayIndexOutOfBoundsException: Index 8 out of bounds for length 8 的根本原因。
我们来逐步剖析原始代码的问题所在:
public static void merge(int[] Arr, int low, int mid, int high) {
int[] arr_left = new int[mid - low + 1]; // 左子数组长度:[low, mid] → 共 mid-low+1 个元素
int[] arr_right = new int[high - mid]; // 右子数组长度:[mid+1, high] → 共 high-mid 个元素
for (int i = 0; i < Arr.length; i++) { // ❌ 错误:用 Arr.length(=8)作为循环上限!
if (i <= mid) {
arr_left[i] = Arr[low + i]; // 当 i=4 时,arr_left[4] 越界(arr_left 长度仅 4)
} else {
arr_right[i] = Arr[mid + 1 + i]; // 当 i=4 时,Arr[mid+1+i] = Arr[3+1+4]=Arr[8] → 越界!
}
}
}关键错误有两点:
-
循环范围错误:
for (int i = 0; i 应改为分别遍历两个子数组的<strong>各自有效索引范围</strong>,而非原数组总长; -
索引逻辑错位:
arr_left[i]和arr_right[i]中的i是全局循环变量,但子数组长度远小于原数组(如示例中arr_left.length = 4,arr_right.length = 4),而i最大可达7,必然越界。
✅ 正确做法是:为左右子数组分别建立独立的、长度匹配的循环:
public static void merge(int[] arr, int low, int mid, int high) {
// 创建左右子数组(注意长度计算)
int[] left = new int[mid - low + 1];
int[] right = new int[high - mid]; // 注意:[mid+1, high] 共 high - mid 个元素
// ✅ 正确:用子数组长度驱动循环,i 仅在 left 合法范围内(0 ~ left.length-1)
for (int i = 0; i < left.length; i++) {
left[i] = arr[low + i];
}
// ✅ 正确:j 从 0 开始,覆盖 right 全长
for (int j = 0; j < right.length; j++) {
right[j] = arr[mid + 1 + j];
}
System.out.println("Left: " + Arrays.toString(left));
System.out.println("Right: " + Arrays.toString(right));
}? 补充说明:示例输入
arr = {38,27,43,10,56,27,18,32},low=0,high=7,mid=3(整数除法),则
left长度 =3−0+1 = 4→ 对应[38,27,43,10]right长度 =7−3 = 4→ 对应[56,27,18,32]
若仍用i (即 <code>i ),当 <code>i=4时:
→left[4]访问非法(left最大索引为3);
→arr[mid+1+i] = arr[3+1+4] = arr[8],而arr索引最大为7。
? 总结与最佳实践:
- 永远用目标数组的
.length控制其对应循环,避免跨数组复用索引变量; - 子数组切分务必验证边界:
left覆盖[low, mid],right覆盖[mid+1, high]; - 建议在开发中启用 IDE 调试器或添加日志(如
System.out.printf("i=%d, left.len=%d%n", i, left.length);)快速定位索引状态; - 完整 Merge Sort 还需后续的三指针合并逻辑(
i,j,k分别指向 left/right/原数组),但子数组构建阶段的健壮性是后续步骤的前提。
遵循以上原则,即可彻底规避此类低级但高频的数组越界异常,让归并排序的实现既正确又可维护。

















