归并排序与那些基于交换、选择等排序的思想不一样,“归并”的含义是将两个或两个以上的有序表组合成一个新的有序表。
其思想是:
假定待排序表含有 n 个记录,则可将其视为 n 个有序的子表,每个子表的长度为 1 ,然后两两归并,得到 ⌈ n / 2 ⌉ (向上取整)个长度为 2 或 1 的有序表:再两两归并…如此重复,直到合并成一个长度为 n 的有序表为止。
如图:
辅助数组问题:对于归并排序的辅助数组,这里的代码是 O ( n ),即整个算法就一个辅助数组,设置一个长度为n的辅助数组,并为全局变量,每次迭代都可使用 。
k路归并:对于 N 个元素进行 k 路归并排序时,排序的趟数 m 满足,k^m = N,从而 m = logk(N),又考虑到 m 为整数,所以 m = ⌈ logk(N) ⌉ 。
时间复杂度问题:每趟排序时间复杂度为 O ( n ),共需要进行 O ( logn )趟,故总的时间复杂度为 O ( nlogn ) 。
算法实现:
/*
2路归并排序:
时间复杂度->最好情况:O(nlogn)、平均情况:O(nlogn)、最坏情况:O(nlogn)
空间复杂度->O(n)
是否稳定->是
*/
#include<bits/stdc++.h>
using namespace std;
typedef int ElemType;
#define n 6
ElemType *B=(ElemType *)malloc((n+1)*sizeof(ElemType));//申请辅助空间
void Merge(ElemType A[],int low,int mid,int high){
int i,j,k;
for(int k=low;k<=high;k++){//将A[]中的元素复制到辅助数组中去
B[k]=A[k];
}
for(i=low,j=mid+1,k=i;i<=mid&&j<=high;k++){//将B[]中较大的先复制到A[]中
if(B[i]<=B[j]){//此处的小于等于号决定了归并排序是一个稳定的排序
A[k]=B[i++];
}
else{
A[k]=B[j++];
}
}
while(i<=mid) A[k++]=B[i++];//将剩余的全部复制到A[]中国
while(j<=high) A[k++]=B[j++];
}
void MergeSort(ElemType A[],int low,int high){
if(low<high){
int mid=(low+high)/2;
MergeSort(A,low,mid);
MergeSort(A,mid+1,high);
Merge(A,low,mid,high);
}
}
int main(){
ElemType A[n]={5,4,2,3,1,0};
MergeSort(A,0,n-1);
for(int i=0;i<n;i++){
cout<<A[i]<<" ";
}
return 0;
}