说到归并排序,其实归并排序还是比较重要的,归并归并,就是先分后并,也就和分治法比较相似了,直切主题吧,我们来谈谈归并排序的基本思想,就是先将数组平均分为两部分,看其中两部分是否有序,若两部分都已经有序,则只需要把他两合并成一个新的数列即可,但要是两个数组还是无序的,我们就要再分,直到里面只有一个元素的时候或里面的元素已经有序。然后我们再将它们一步一步地合并起来。
文字可能不太好理解,那我来给大家画几张图看看吧
首先我们随便给些数
然后我们开始给他们分成2部分
发现各部分还是无序的,那我们就继续分
直到分到1个1个的,那么就每个里面就默认有序了,好了,既然有序了,那么我们就要合并了,那就合么。
合并完了,数列也就有序了。
接下来就用代码给大家讲讲吧,自己写了遍发现有些地方容易出错
void Merge(int *arr,int *brr,int start,int mid,int end)
{
int left=start;
int right=mid+1;
int tmpindex=start;
while(left !=mid+1&&right !=end+1)//把小的数放入到brr中
{
if(arr[left]>arr[right])
{
brr[tmpindex++]=arr[right++];
}
else
{
brr[tmpindex++]=arr[left++];
}
}
while(left !=mid+1)//这是左边可能没放完
{
brr[tmpindex++]=arr[left++];
}
while(right !=end+1)//这是右边可能没放完
{
brr[tmpindex++]=arr[right++];
}
for(int i=start;i<=end;i++)//把brr中的数再放回到arr中
{
arr[i]=brr[i];//注意这里是可以=end的
}
}
void MergeSort(int *arr,int *brr,int start,int end)
{
if(start<end)
{
int mid=(start+end)/2;
MergeSort(arr,brr,start,mid);//左边有序
MergeSort(arr,brr,mid+1,end);//右边有序
Merge(arr,brr,start,mid,end);//再合并
}
}
再分析一下这个程序,它是一个稳定的算法,时间复杂度是O(nlogn);
其实思路出来了,就很好实现了,但是我们用的是递归方法,但很多时候是让我们去写一个非递归,所以我们就再写一个非递归:
void New_MergeSort(int arr[],int brr[],int len)
{//非递归实现
int size=1,low,mid,high;
while(size<=len-1)
{
low=0;
while(low+size<=len-1)
{
mid=low+size-1;
high=mid+size;
if(high>len-1)//第二个序列个数不足size
high=len-1;
Merge(arr,brr,low,mid,high);//调用归并子函数
low=high+1;//下一次归并时第一关序列的下界
}
size*=2;//范围扩大一倍
}
}