写完了时间复杂度O(n^2)的几大经典排序算法,接下来开始写时间复杂度O(nlogn)的排序算法
这篇文章先介绍归并排序的递归实现以及迭代实现
1.概念
归并排序采用分治的思想,将一组无序的数据平均分为多个小块,分到极限时,每一块仅包含1个数据,此时每块都是有序的。接下来进行归并操作。下图为维基百科gif图
2.递归实现
template<typename T>
void __merge(T arr[],int l,int middle,int r){
T temp[r-l+1];
int k=0;
int i = l;
int j = middle+1;
//下标正确范围内 进行排序
while(i<=middle && j<=r){
temp[k++] = arr[i]<=arr[j]?arr[i++]:arr[j++];
}
//退出while循环 存在下标越界
while(i<=middle){
temp[k++]=arr[i++];
}
while(j<=r){
temp[k++]=arr[j++];
}
for(int i=0;i<r-l+1;i++){
arr[i+l] = temp[i];
}
}
template<typename T>
void __mergeSort(T arr[],int l,int r){
if(r-l<=15){ //基于插入排序的特性进行小优化(包括快速排序中也可以使用此优化)
insertionSort(arr,l,r);//对于归并过程,当剩余未排序元素越少时,这些元素的有序性越高,
return ; //对于插入排序而言,时间复杂度进化到O(n)级别
}
int middle = (l+r)/2;
__mergeSort(arr,l,middle);
__mergeSort(arr,middle+1,r);
if(arr[middle]>arr[middle+1]) //此处是比较大的优化
__merge(arr,l,middle,r); //举例:1 2 和 3 4 两组数据进行归并 两组数据各自都是有序的
//此时因为2<3 所以 1234已经有序 无需进行merge操作
}
template<typename T>
void mergeSort(T arr[],int n){
__mergeSort(arr,0,n-1);
}
3.迭代实现(自底向上)
//自底向上 非递归算法
template<typename T>
void mergeSortBU(T arr[],int n){
for(int size=1;size<=n;size*=2){
for(int i=0;i+size<n;i+=2*size){
__merge(arr,i,i+size-1,min(i+2*size-1,n-1));
}
}
}
4.性能测试
测试样本n=50000 range:0~50000的随机整数数组和完全有序数组
下文介绍基于归并排序实现一些相关的算法