一、排序过程
分为两个大步骤,分解和合并

分解

找到mid,然后分解即可,直到 left == right
合并
合并的思路是把每个小组比较后放入一个新的临时数组里,然后再赋值即可

二、代码实现
java
public static void mergeSort(int[] arr) {
mergeSortTmp(arr,0,arr.length - 1);
}
//分解
private static void mergeSortTmp(int[] arr, int left, int right) {
if(left >= right) return;
int mid = (left + right) / 2;
mergeSortTmp(arr, left, mid);
mergeSortTmp(arr, mid + 1, right);
merge(arr,left,mid,right);
}
//合并
private static void merge(int[] arr, int left, int mid, int right) {
int[] tmp = new int[right - left + 1];
int k = 0;
int s1 = left;
int s2 = mid + 1;
while(s1 <= mid && s2 <= right) {
if(arr[s1] >= arr[s2]){
tmp[k++] = arr[s2++];
}else{
tmp[k++] = arr[s1++];
}
}
while(s1 <= mid){
tmp[k++] = arr[s1++];
}
while(s2 <= right){
tmp[k++] = arr[s2++];
}
for(int i = 0;i < k;i++){
arr[left+i] = tmp[i];
}
}
**arr[s1] >= arr[s2]**其实 换成 > ,结果也是一样的。但是如果真的出现向相等的情况,使用 > 的话,代码会多执行,从效率上考虑,选择 >= 时比较好的
三、非递归实现代码
java
public static void mergeSortNor(int[] arr) {
int gap = 1;
while(gap < arr.length){
for(int i = 0;i < arr.length;i = i + gap * 2){
int left = i;
int mid = left + gap - 1;
if(mid >= arr.length){
mid = arr.length - 1;
}
int right = mid + gap;
if(right >= arr.length){
right = arr.length - 1;
}
merge(arr,left,mid,right);
}
gap *= 2;
}
}
在上面代码中加入这个方法即可,将分组的形式转变成以gap分组的形式进行
四、归并的特性
-
归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。
-
时间复杂度:O(N*logN)
-
空间复杂度:O(N)
-
稳定性:稳定