算法描述
是建立在归并操作上的一种有效,稳定的排序算法,该算法是采用分治法的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
归并操作的工作原理如下:
第一步:申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
第二步:设定两个指针,最初位置分别为两个已经排序序列的起始位置
第三步:比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
重复步骤3直到某一指针超出序列尾
将另一序列剩下的所有元素直接复制到合并序列尾
图解
参考代码
public class MergeSort {
public static void main(String[] args) {
int[] arr = new int[20];
Random random = new Random();
for (int i = 0; i < arr.length; i++) {
arr[i] = random.nextInt(50);
}
mergeSort(arr, 0, arr.length - 1);//递归实现——要有边界
System.out.println(Arrays.toString(arr));
}
private static void mergeSort(int[] arr, int l, int r) {
if (l == r) {
return;
}
// 分的过程
int mid = (l + r) / 2;
mergeSort(arr, l, mid);
mergeSort(arr, mid + 1, r);
// 并的过程
merge(arr, r, mid, l);
}
private static void merge(int[] arr, int r, int mid, int l) {
int[] temp = new int[r - l + 1];
for (int k = l; k <= r; k++) {
temp[k - l] = arr[k];
}
int i = l;//标记合成(新数组)数组左边的角标
int j = mid + 1;//标记合成数组(新数组)右边的角标
int k;//标记原数组角标
// 在新数组中比较 返回的结果给原数组
for (int m = l; m <= r; m++) {
if (i > mid) {
arr[m] = temp[j - l];//arr[m]=temp[j] 数组 左边结束
j++;
} else if (j > r) {
arr[m] = temp[i - l];//arr[m]=temp[i] 数组 右边遍结束
i++;
} else if (temp[i-l] < temp[j-l]) {//数组 左边元素<右边元素
arr[m] = temp[i - l];
i++;
} else {
arr[m] = temp[j - l];//数组 左边元素>右边元素
j++;
}
}
}
}
算法性能
-
时间复杂度
O(nlogn) -
空间复杂度
O(n) -
算法稳定性
稳定