归并排序(Merge Sort)是一种基于分治思想(Divide and Conquer)的高效排序算法,其核心步骤包括分解、排序、合并。以下是Java中归并排序的实现及详细解析:
1. 归并排序原理
- 分解:将数组递归地分成两半,直到子数组长度为1(天然有序)。
- 排序:对两个有序子数组进行合并,生成更大的有序数组。
- 合并:通过双指针比较两个子数组的元素,按序合并到临时数组,再复制回原数组。
2. Java实现代码
java
public class MergeSort {
// 主方法:对外接口
public static void sort(int[] arr) {
if (arr == null || arr.length <= 1) {
return;
}
int[] temp = new int[arr.length]; // 临时数组用于合并
mergeSort(arr, 0, arr.length - 1, temp);
}
// 递归分治
private static void mergeSort(int[] arr, int left, int right, int[] temp) {
if (left < right) {
int mid = left + (right - left) / 2; // 防止溢出
mergeSort(arr, left, mid, temp); // 左半部分排序
mergeSort(arr, mid + 1, right, temp); // 右半部分排序
merge(arr, left, mid, right, temp); // 合并两个有序数组
}
}
// 合并两个有序子数组
private static void merge(int[] arr, int left, int mid, int right, int[] temp) {
int i = left; // 左子数组起始索引
int j = mid + 1; // 右子数组起始索引
int k = 0; // 临时数组索引
// 比较左右子数组元素,填入临时数组
while (i <= mid && j <= right) {
if (arr[i] <= arr[j]) {
temp[k++] = arr[i++];
} else {
temp[k++] = arr[j++];
}
}
// 处理剩余元素(左子数组)
while (i <= mid) {
temp[k++] = arr[i++];
}
// 处理剩余元素(右子数组)
while (j <= right) {
temp[k++] = arr[j++];
}
// 将临时数组复制回原数组
System.arraycopy(temp, 0, arr, left, k);
}
public static void main(String[] args) {
int[] arr = {12, 11, 13, 5, 6, 7};
System.out.println("排序前: " + Arrays.toString(arr));
sort(arr);
System.out.println("排序后: " + Arrays.toString(arr));
}
}
3. 关键点解析
- 递归终止条件 :当子数组长度为1时(
left >= right)停止分解。 - 临时数组:避免每次合并时新建数组,提升性能。
- 稳定性 :归并排序是稳定的(
arr[i] <= arr[j]中的等号保证相等元素的原始顺序)。 - 时间复杂度 :
- 最优/最差/平均:均为 (O(n \log n)),因为分解和合并的层次均为 (\log n),每层合并操作耗时 (O(n))。
- 空间复杂度:(O(n)),需额外临时数组。
4. 优化方向
- 小数组优化:对小规模子数组(如长度<15)切换为插入排序。
- 避免重复拷贝 :通过参数传递临时数组的当前有效段,减少
System.arraycopy调用。 - 并行化:利用多线程对左右子数组的排序过程并行处理(适用于大规模数据)。
5. 对比其他排序算法
| 算法 | 时间复杂度(平均) | 空间复杂度 | 稳定性 |
|---|---|---|---|
| 归并排序 | (O(n \log n)) | (O(n)) | 稳定 |
| 快速排序 | (O(n \log n)) | (O(\log n)) | 不稳定 |
| 堆排序 | (O(n \log n)) | (O(1)) | 不稳定 |
6. 适用场景
- 大数据量排序:如外部排序(数据无法全部加载到内存)。
- 链表排序:无需随机访问,合并操作更高效。
- 需要稳定排序的场景:如按多关键字排序时,前序关键字的排序结果需保留。
通过分治和合并的巧妙设计,归并排序在保证稳定性的同时实现了高效排序,是理解算法分治思想的经典案例。