任意给出一行随机数,对这些随机数从小到大,进行归并排序。
这里只是简单的没有用到递归,后续的改进算法思想:1、不回写(减少这里copy()函数),2、不逆序,(组合片段时,选择那些已经是顺序的片段,例如(3,5,6),(4),(2),(7,8)),3、与插入结合(因为可以证明,当每个片段的长度<=16时,插入排序较好,所以可以选择片度小于16的进行插入排序,然后进行归并)。
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define LEN 37
void merge(int i, int j, int d);
void print(int a[]);
void copy();
int a[LEN];
int b[LEN];
void main(void)
{
int i,j,d;
srand((unsigned int)time(NULL));
for(i=0; i<LEN; i++)
{
a[i]=rand()%LEN+1;
}
printf("排序之前的序列:\n");
print(a);
printf("\n");
//归并的基本思想:把一个长序列,先一个数占一个片段,然后两两按序合并,合并的有序的片段再与其它
//合并的有序片段进行合并,直到整个序列都是有序的,
//用i表示第一个片段的起始位置,用j表示第二个片段的起始位置,
//d表示两个片段之间的跨度,进行两两合并
d=1;
while(d<LEN)
{
i=0;
j=i+d;
while(j<LEN+1)
{
merge(i,j,d);
//定位下一对片段位置
i=i+2*d;
j=j+2*d;
}
d=2*d; //新的跨度
copy();
//printf("\n***a[0]=%d***\n",a[0]);
}
printf("排序之后的序列:\n");
print(b);
printf("\n");
}
//把两个有序序列合并到一个序列中
void merge(int i, int j, int d)
{
int k=i;
int leni=i+d;
int lenj;
if(j+d>LEN)
{
lenj=LEN;
}
else
{
lenj=j+d;
}
while(i<leni && j<lenj)
{
if(a[i]>a[j])
{
b[k]=a[j];
k++;
j++;
}
else
{
b[k]=a[i];
k++;
i++;
}
}
while(i<leni)
{
b[k]=a[i];
i++;
k++;
}
while(j<lenj)
{
b[k]=a[j];
j++;
k++;
}
}
void print(int a[])
{
int i;
for(i=0; i<LEN; i++)
{
printf("%3d\t",a[i]);
}
}
void copy()
{
int i;
for(i=0; i<LEN; i++)
{
a[i]=b[i];
}
}