归并排序 MergeSort
1、问题
使用归并排序对 n 个不同的数构成的数组 A [ 1.. n ] 进行排序,其中 n=2^k。
2、解析
归并排序是通过二分和分治的思想,通过不断地递归二分数组,直到每个子数组都只有一个元素,此时因为每个数组都只有一个元素所以均是有序的。
之后再通过有序表的归并,重组每个独立的数组,直到最后得到一个有序的完整数组。
3、设计
1 void merge(int L, int R) {//有序数组的归并 2 len <- (L + R >> 1) - L+1; 3 posl <- L;//L数组的起始位置 4 posr <- L + len;//R数组的起始位置 5 posb <- L; 6 while posl < L + len and posr <= R 7 //从开始位置比较,如果L数组的元素大于R数组,则将L数组的元素存进去一个,然后位置+1,否则相反 8 if A[posl] <= A[posr] 9 B[posb++] = A[posl++] 10 else 11 B[posb++] = A[posr++] 12 } 13 while posl < L + len//如果L数组没有放完就直接放在最后面 14 B[posb++] = A[posl++] 15 while posr <= R //如果R数组没有放完就直接放在最后面 16 B[posb++] = A[posr++] 17 } 18 void mergesort(int L, int R) {//归并排序 19 if R == L 20 return;//递归到每组只有一个元素返回,因为此时必定有序 21 int mid <- L + R >> 1//找到每个分块的中间值 22 mergesort(L, mid);//左边递归进行分离和合并 23 mergesort(mid+1, R);//右边递归进行分离和合并 24 merge(L, R);//左右合并 25 for i <- L to R 26 A[i] = B[i]//排好序的结果传给A数组 27 }
4、分析
归并排序需要多次分治和进行有序表的合并操作,所以归并排序总时间=子序列排好序时间+合并时间
一个数组长度为n,二分子区间最多有log2(n)层,所以时间复杂度为n*O(1)+n*log2(n),约等于nlog2(n)
5、源码
https://github.com/ChenyuWu0705/Algorithm-Analyze-and-Design/blob/main/Merge%20Sort.cpp