#include<stdio.h>
struct st
{
 int key;
 int xb;//下标
};
void merge(struct st a[],struct st temp[],int u,int m,int v)// 一次归并(以a[].key从小到大将结构体排序)
{
 int i,j,k,t;
 i=u;//i从第一段的起始位置开始,一直到最终位置m;
 j=m+1;//j从第2段的起始位置开始,一直到最终位置v
 k=u;//k表示的是目标b[]的起始位置
 while(i<=m&&j<=v)//将两段与序元素中元素值较小的元素依次放入目标b[]中
 {
  if(a[i].key<=a[j].key)//若要以a[].v从小到大将结构体排序,则只需在此处将a[i].key<=a[j].key改为a[i].key>=a[j].key
   {temp[k]=a[i]; i++;}
  else {temp[k]=a[j]; j++;}
  k++;
 }
 if(i<=m) //将第一段剩余元素放入目标b[]中
  for(t=i;t<=m;t++)
   temp[k+t-i]=a[t];
 else
  for(t=j;t<=v;t++)
   temp[k+t-j]=a[t];
}
void mergepass(struct st a[],struct st temp[],int len,int alen)//一趟归并(alen为a的长度,len为待归并的有序段的长度)
{
 int i=0,j;
 while(i<=alen-2*len)//以i为起点,长度为len的相邻两个有序段依次进行归并
 {
  merge(a,temp,i,i+len-1,i+2*len-1);//一次归并
  i=i+2*len;//置下一个一次归并的起始位置
 }
 if(i+len-1<alen-1)//对剩下的1个长为len ,另 1个长度不足len,终点为n的两个有序段归并
  merge(a,temp,i,i+len-1,alen-1);
 else
  for(j=i;j<alen;j++)//对剩下的1个长不足len
   temp[j]=a[j];
}//本算法结束后b[]中的有序段的长度为2*len
void mergesort(struct st a[],int alen)//归并排序算法(a为待排序的数组,temp为辅助存储空间)
{
 int len=1;//初始时有叙段长度为1
 struct st *temp=new struct st[alen];
 while(len<alen)
 {
  mergepass(a,temp,len,alen);//一趟归并,结果在b[]中
  len=2*len;
  mergepass(temp,a,len,alen);//一趟归并,结果在a[]中
  len=2*len;
 }
 delete temp;
}
int main()
{
 int i,n;
 printf("请输入待排序数组长度:");
 scanf("%d",&n);
 struct st *a=new struct st[n];
 printf("请依次输入待排序数组元素:\n");
 for(i=0;i<n;i++)
  scanf("%d",&a[i].key);
 for(i=0;i<n;i++)
  a[i].xb=i;
 mergesort(a,n);//归并排序
 printf("归并排序后结果:\n");
 for(i=0;i<n;i++)
  printf("%d(%d) ",a[i].key,a[i].xb);
 printf("\n");
 delete a;
 return 0;
}
/*
请输入待排序数组长度:15
请依次输入待排序数组元素:
3 89 54 26 45 38 45 3 65 47 26 33 198 45 3
归并排序后结果:
3(0) 3(7) 3(14) 26(3) 26(10) 33(11) 38(5) 45(4) 45(6) 45(13) 47(9) 54(2) 65(8) 89(1) 198(12)
Press any key to continue
*/