template
void mergeAB(T a[],int l,int m,int r)
{
T *b=new T[r-l+1];
for(int i=l;i<=r;i++)
b[i-l]=a[i];
int start1=0,start2=m-l+1,start3=l;
while(start1<=m-l && start2<=r-l)
{
if(b[start1]
void mergeSort(T a[],int l,int r)
{
if(l>=r) return ;
mergeSort(a,l,(l+r)/2);
mergeSort(a,(l+r)/2+1,r);
mergeAB(a,l,(l+r)/2,r);
}
对合并排序的优化主要是对其递归上进行简化。和快速排序一样,当合并排序进行递归的数组长度足够小时,可以改用插入排序,因为小规模上插入排序来得更有优势。那么,我们令当排序数组长度小于M=10时,采用插入排序,
template
void insertion(T a[],int l,int r)
{
for(int i=l+1;i<=r;i++)
{
T v=a[i];
int j=i;
while(j>l && v
void mergeSort_M(T a[],int l,int r)
{
if(r-l
除了减少递归次数,还有就是采用模拟递归技术,我们知道合并排序就是将元素两两合并,那么可以从数组左端开始,令步长h=1,每隔两个步长就执行一次合并,再令步长h=h+h,重复上述直到步长超过数组长度,这种方法叫自底而上合并排序(mergeBU)。
template
void mergeBU(T a[],int l,int r)
{
for(int m=1;m
观察mergeBU发现,以步长为1为起始是因为只有一个元素的数组是有序的,那么就可以放心地进行合并。但实际上,数组的一些元素本来便是有序的,如{4,2,3,9,1,5,6}中可以由分为有序的三个部分{4},{2,3,9},{1,5,6},这样我们只需对三个有序的进行合并排序即可,这种方法更加自然,所以称为自然合并排序。基本思想就是对数组进行一次扫描,划分为有序的部分,再进行合并排序。自然合并排序对有序的数组只需进行时间为o(n)的扫描,相对地mergeBU需要o(nlogn)。
template
void naturalMergeSort(T a[],int l,int r)
{
while(1)
{
int start=l;
int m=l;
int end=l;
int flag=0;
for(int i=l+1;i<=r;i++)
{
if(a[i]=a[end])
{
end=i;
}
}
mergeAB(a,start,m,end);
if(start==l && end==r) break;
}
}
下面测试长度为十万的随机数组,元素取值范围为[1,99999]的排序时间比较结果,
template
void print(string name,void(*sortName)(T* ,int ,int ),T a[],int length){
clock_t start=clock();
sortName(a,0,length-1);
clock_t end=clock();
cout<