描述: 归并排序就是将两个或两个以上有序表合并成一个有序表的过程。将两个有序表合并成一个有序表的过程称为2-路归并,下面以2-路归并为例其排序过程是:
- 假设初始序列有n个元素,则可看成n个长度为1有序子序列,然后两两归并,得到(向上取整,大于等于n/2的最小整数)个长度为2或1(奇数个元素剩个元素单独成列)的有序子序列;再两两归并,如此重复,直到得到一个长度为n的有序序列为止。
- 其中两个有序子序列合并成一个序列的过程为:初始两子序列下标都指向首元素,每次都比较两下标元素,小的放入辅助数组并下标后移一位,直至其中一个数组全部完成比较,将另一个数组剩下的元素全部放进辅助数组。
java代码
import java.util.Arrays;
public class MergeSort {
// 外部调用接口
public static void mergeSort(int[] arr) {
// 避免递归过程中频繁开辟空间,开始建一个长度的等于原数组长的临时数组
int[] temp = new int[arr.length];
sort(arr, 0, arr.length - 1, temp);
}
private static void sort(int[] arr, int left, int right, int[] temp) {
// 递归出口left=right,即子序列长度为1
if (left < right) {
int mid = (left + right) / 2;
sort(arr, left, mid, temp); // 对左子序列递归调用并归完成排序
sort(arr, mid + 1, right, temp); // 对右子序列递归调用并归完成排序
merge(arr, left, mid, right, temp); // 将两个有序子序列合并
}
}
// 将传入数组arr一分为二排序好后返回给原数组位置
private static void merge(int[] arr, int left, int mid, int right, int[] temp) {
int i = left;
int j = mid + 1;
int t = 0;
while (i <= mid && j <= right)
temp[t++] = arr[i] < arr[j] ? arr[i++] : arr[j++];
while (i <= mid)
temp[t++] = arr[i++];
while (j <= right)
temp[t++] = arr[j++];
t = 0;
while (left <= right)
arr[left++] = temp[t++];
}
// 测试
public static void main(String[] args) {
int[] arr = new int[1000];
for (int i = 0; i < 1000; i++)
arr[i] = (int) (Math.random() * 999 + 1);
mergeSort(arr);
System.out.println(Arrays.toString(arr));
}
}
算法分析
- 时间复杂度,n个元素需进行趟归并排序,每一趟归并,比较次数不超过n,移动次数2n,因此归并排序时间复杂度。
- 空间复杂度,只用到了和原数组一样长的临时数组。
- 稳定性取决于第28行三元表达式,就上面代码来说排序不稳定,将“<”换成“<=”后稳定,因为值相等时会将左边子序列元素放入辅助数组前面。
来源:CSDN
作者:纯真飞鱼
链接:https://blog.csdn.net/okayok/article/details/104558943