一、 10大排序算法
二、归并排序原理图:
三、归并排序代码的递归实现
图1
需要注意的地方
1.Merge函数为什么要传入这些参数呢?
想一下,抛开归并,你要合并两个肩并肩的数组要怎么做呢,要知道两个数组的起点和终点,通过下面三个参数可以算出来这两个数组的起点和终点(如上图,图1所示)
左边部分的起点和终点分别为 Left 和 RightLeft-1
右边部分的起点和终点分别为 RightLeft 和 RightEnd
void Merge(int a[],int tmp[],int left,int rightLeft,int rightEnd){
int leftEnd=rightLeft-1;
int length=rightEnd-left+1;
int i=left;
while((left<=leftEnd)&&(rightLeft<=rightEnd)){
if(a[left]<=a[rightLeft]){
tmp[i++]=a[left++];
} else{
tmp[i++]=a[rightLeft++];
}
}
while(left<=leftEnd){//右边全部导入tmp,左边还有剩余
tmp[i++]=a[left++];
}
while(rightLeft<=rightEnd){
tmp[i++]=a[rightLeft++];
}
//再将tmp倒回到a中
for(int i=0;i<length;i++,rightEnd--){
a[rightEnd]=tmp[rightEnd];
}
}
递归的方法还是很好理解的,重点强调一定要先理解递归排序的原理,最好结合图进行记忆
void MSort(int a[],int tmp[],int left,int right){
if(left>=right){
return;
}
int mid= (left+right)/2;
MSort(a,tmp,left,mid);
MSort(a,tmp,mid+1,right);
Merge(a,tmp,left,mid+1,right);
Dump(a,20,1);
}
2、为什么tmp这个临时数组要先申请,并随参数一直带着呢?明明只是在merge函数里才用到。
原因:
如果在merge函数里申请,就会不停的申请释放空间,效率低。
在外面申请的话只需要申请、释放一次即可
void MergeSort(int a[],int size){
if(size<=1) {
printf("Too few elements");
return;
}
int *tmp =(int*)malloc(size* sizeof(int));
if(nullptr==tmp){
printf("malloc memery error");
return;
}
else{
MSort(a,tmp,0,size-1);
free(tmp);
}
}
//测试
void Dump(int a[],int size,int times){
for(int i=0;i<size;++i){
if(i==0){
printf("sort %dth: ",times);
}
printf("%d ",a[i]);
}
printf("\r\n");
}
int main() {
int a[20]={1,6,3,5,2,0,4,9,7,8,30,11,23,56,78,89,33,67,43,22};
Dump(a,20,0);
MergeSort(a,20);
return 0;
}
归并排序的递归实现需要因为递归算法本身的限制,所以效率不高,归并算法还可以用非递归的形式来实现。