归并排序(Merge Sort)
归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。
算法描述
- 把长度为n的输入序列分成两个长度为n/2的子序列;
- 对这两个子序列分别采用归并排序;
- 将两个排序好的子序列合并成一个最终的排序序列。
例子
数组: 3 17 12 11 2 20 27 23
先分两组:3 17 12 11 | 2 20 27 23
每组再分:3 17 ; 12 11 | 2 20 ; 27 23
第一次: 3 17 12 11 2 20 27 23
第二次: 3 17 11 12 2 20 27 23
第三次: 3 11 12 17 2 20 27 23
第四次: 3 11 12 17 2 20 27 23
第五次: 3 11 12 17 2 20 23 27
第六次: 3 11 12 17 2 20 23 27
第七次: 2 3 11 12 17 20 23 27
结束
算法复杂度
空间复杂度: O(n)
时间复杂度:
排序稳定,原来相等的两个参数排在前面的依旧是排在前面。
代码实现
public static int[] sort(int[] sourceArray) throws Exception {
int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);
if (arr.length < 2) {
return arr;
}
int middle = (int) Math.floor(arr.length / 2);
int[] left = Arrays.copyOfRange(arr, 0, middle);
int[] right = Arrays.copyOfRange(arr, middle, arr.length);
return merge(sort(left), sort(right));
}
private static int[] merge(int[] left, int[] right) {
int[] result = new int[left.length + right.length];
int i = 0;
while (left.length > 0 && right.length > 0) {
if (left[0] <= right[0]) {
result[i++] = left[0];
left = Arrays.copyOfRange(left, 1, left.length);
} else {
result[i++] = right[0];
right = Arrays.copyOfRange(right, 1, right.length);
}
}
while (left.length > 0) {
result[i++] = left[0];
left = Arrays.copyOfRange(left, 1, left.length);
}
while (right.length > 0) {
result[i++] = right[0];
right = Arrays.copyOfRange(right, 1, right.length);
}
System.out.println(Arrays.toString(result));
return result;
}
运行结果
输入数组:int[] arr = {3,17,12,11,2,20,27,23};
[3, 17]
[11, 12]
[3, 11, 12, 17]
[2, 20]
[23, 27]
[2, 20, 23, 27]
[2, 3, 11, 12, 17, 20, 23, 27]
但是按照上面的步骤,这时候我们可以看到和演算结果一致。