赶时间的学习记录
归并排序法(Merge Sort,以下简称MS)是分治法思想运用的一个典范。
其主要算法操作可以分为以下步骤:
Step 1:将n个元素分成两个含n/2元素的子序列
Step 2:用MS将两个子序列递归排序(最后可以将整个原序列分解成n个子序列)
Step 3:合并两个已排序好的序列
易知,MS的关键在于Merge过程。对于这一过程的理解,算法导论中给出了一个形象的模型。
即假设桌面上有两堆已排序好的的牌,且每一堆都正面朝下放置。然后我们分别从两堆牌中选取顶上的一张牌(选取之后,堆顶端又会露出新的顶牌),选取较小的一张,放入输出堆,另一张放回。
重复这一步骤,最后直到一堆牌为空。由于两堆牌都是已排序,所以可知,只要将剩下的那堆牌盖到输出堆即完成整个排序过程。
以上来自百度百科,如果没看懂建议去B站找视频看看。
草稿:
完整代码:
#include<stdio.h>
#include<stdlib.h>//分配空间需要用
void merge(int *a,int *temparr,int left,int mid,int right)//合并小问题
{
int lpos=left,rpos=mid+1;
int temppos=left;
while(lpos<=mid && rpos<=right)
{
if(a[lpos]<a[rpos])temparr[temppos++]=a[lpos++];//排序,最小的先放入临时数组
else temparr[temppos++]=a[rpos++];
}
while(lpos<=mid)//左边剩余的数直接放入临时数组
{
temparr[temppos++]=a[lpos++];
}
while(rpos<=right)//右边剩余的数直接放入临时数组
{
temparr[temppos++]=a[rpos++];
}
while(left<=right){a[left]=temparr[left];left++;}//排好序后将这一段的数据覆盖到原数组中
}
void divide_conquer(int *a,int *temparr,int left,int right)//划分成左右两边
{
if(left<right)
{
int mid=(left+right)/2;
divide_conquer(a,temparr,left,mid);
divide_conquer(a,temparr,mid+1,right);//left和right都是数组的下标
merge(a,temparr,left,mid,right);
}
}
void mergesort(int *a,int len)//归并排序入口
{
int *temparr=(int*)malloc(len*sizeof(int));//开辟临时数组,用来合并
if(temparr)
{
divide_conquer(a,temparr,0,len-1);
free(temparr);
}else
{printf("fail to allocate dedicated space!");}
}
int main()
{
int a[]={3,44,40,37,20,1,2,50,15};
int len=sizeof(a)/sizeof(int);
int i;
mergesort(a,len);
for(i=0;i<len;i++)printf("%3d",a[i]);
printf("\n");
return 0;
}
这玩意感觉还是有点难,要多温习几遍才行。