时间复杂度:O(n*logn)
原理:将数组分为若干子数组,各子数组分别排序,最后归并排序
简化版:(将数组二分成若干组,分别进行排序,最后逐步归并)
代码:
// 将arr[l...mid]和arr[mid+1...r]两部分进行归并
template<typename T>
void merge(T arr[], int l, int mid, int r){
// 将数组复制一份以便操作
T aux[r-l+1];
for( int i = l ; i <= r; i ++ ) //注意数据的偏移量 i-l
aux[i-l] = arr[i];
int i = l, j = mid+1;
for( int k = l ; k <= r; k ++ ){
// i 索引所指的子数组中的元素已经归并完
// j 索引所指的子数组中的元素还没有完全归并完
if( i > mid ){
arr[k] = aux[j-l];
j ++;
}
// 情况相反
else if( j > r ){
arr[k] = aux[i-l];
i ++;
}
else if( aux[i-l] < aux[j-l] ){
arr[k] = aux[i-l];
i ++;
}
else{
arr[k] = aux[j-l];
j ++;
}
}
}
// 递归使用归并排序,对arr[l...r]的范围进行排序
template<typename T>
void mergeSort(T arr[], int l, int r){
//当前处理的数据集为空
if( l >= r )
return;
int mid = (l+r)/2;
//将arr[l...mid]和arr[mid+1...r]排序
mergeSort(arr, l, mid);
mergeSort(arr, mid+1, r);
//若arr[mid] <= arr[mid+1],则不用归并
if ( arr[mid] > arr[mid+1] )
merge(arr, l, mid, r); //将两部分归并
}
优化:(元素数据比较小时,转而使用插入排序性能更高,原因:元素数据较小时,数据近乎有序的几率比较大,此时插入排序有优势)
// 递归使用归并排序,对arr[l...r]的范围进行排序
template<typename T>
void mergeSort(T arr[], int l, int r){
if( r - l <= 15 ){ //15 只是随机列举的,范围可视情况而定
insertionSort(arr, l, r);
return;
}
。
。
。
}
自底向上的归并排序:
template <typename T>
void mergeSortBU(T arr[], int n){
for( int sz = 1; sz <= n ; sz += sz )
for( int i = 0 ; i < n ; i += sz+sz )
// 对 arr[i...i+sz-1] 和 arr[i+sz...i+2*sz-1] 进行归并
merge(arr, i, i+sz-1, min(i+sz+sz-1,n-1) );
}
优化:
template <typename T>
void mergeSortBU(T arr[], int n){
for( int i = 0 ; i < n ; i += 16 )
insertionSort(arr,i,min(i+15,n-1));
for( int sz = 16; sz <= n ; sz += sz )
for( int i = 0 ; i < n - sz ; i += sz+sz )
if( arr[i+sz-1] > arr[i+sz] )
merge(arr, i, i+sz-1, min(i+sz+sz-1,n-1) );
}