一、基本思路
1、确定分界点
分界点:中点-mid
mid = (l + r)/ 2; 此处取的是中点的索引,而非值本身
2、递归排序 left、right 两部分
1、保证 left 与 right 是已经排好序的两个序列
2、当递归到最小的只有一个元素的时候,进行返回
3、然后对所得到的两个元素进行归并排序,而后递归,保证左右两都是有序的
3、归并排序——合二为一
1、创建 temp[r - l + 1]的暂存矩阵
2、选择左、右指针中小的那个放入 temp 中,然后此指针后移一位
3、继续比较、假如一个序列到顶点,则将另一个剩下部分拼在后面
二、Java、C语言模板实现
//Java 模板实现
import java.util.Scanner;
import java.util.stream.IntStream;
public class Practice {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int[] arr = IntStream.range(0, n).map(i -> scanner.nextInt()).toArray();
mergeSort(arr, 0, n-1); // 可以不用数组接收,是因为进行的是引用地址值的传递,是地址的副本进行了传递
IntStream.range(0, n).mapToObj(i -> arr[i] + " ").forEach(System.out::print);
}
private static int[] mergeSort(int[] arr, int left, int right){
if (left >= right){ // 判断是否是1个元素
return arr;
}
int[] temp = new int[right - left + 1]; // 暂存数组
int mid = left + right >> 1; // 取中间点坐标索引
int i = left; // 左边序列移动指针
int j = mid + 1; // 右边序列的移动指针
int k = 0; // 存储数组的指针
mergeSort(arr, left, mid); // 递归左边序列
mergeSort(arr, mid + 1, right); // 递归右边序列,此处是后面进行归并的前前提,是因为本身默认已经做好了排序了
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 循环外面
}
while (j <= right){
temp[k++] = arr[j++];
}
for (i = left,j = 0;i <= right; i++, j++){ // 因为是传递的地址值,那么此处实际上反传递回去,对arr进行修改
arr[i] = temp[j];
}
return arr;
}
}
```c
// C语言实现,此处是yxc实现
void merge_sort(int q[], int l, int r)
{
if (l >= r) return;
int mid = l + r >> 1;
merge_sort(q, l, mid);
merge_sort(q, mid + 1, r);
int k = 0, i = l, j = mid + 1;
while (i <= mid && j <= r)
if (q[i] <= q[j]) tmp[k ++ ] = q[i ++ ];
else tmp[k ++ ] = q[j ++ ];
while (i <= mid) tmp[k ++ ] = q[i ++ ];
while (j <= r) tmp[k ++ ] = q[j ++ ];
for (i = l, j = 0; i <= r; i ++, j ++ ) q[i] = tmp[j];
}
作者:yxc
链接:https://www.acwing.com/blog/content/277/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
三、注意事项
1、注意归并排序与快排的区别:归并排序是先归并,然后再进行归并操作,归并操作已经是两个排好序的数组;快排是先进行粗略分界,然后再进行递归。
2、归并排序复杂度为O(n)