一.直接插入排序
在希尔排序之前,我们先来看一下比较简单的直接插入排序。其算法思想主要是,将一个无序的数据插入到已经排好序的有序表中,从而得到一个数据量+1的有序表。以此类推,便可将所有数据变为有序。
这种思想在生活中十分常见,比如你有一堆无序的作业,你会看一下第二份作业的序号,然后与第一份作业的序号相比,如果大于,则第二份放在最上面,否则位置不动。在这个过程中,第一份作业就是一个有序表(一个数据必定有序),然后操作完成后,你便得到了有2个数据的有序表。接下来,第3个,第4个.....直到全部有序。
时间复杂度:O(n^2),需要一个数据的辅助空间。
代码:
for(int i=2;i<max;i++)//直接插入排序,从第二个数据开始
{ //data数组从data[1]开始存放数据
int j;
data[0]=data[i];//data[0]用来暂存要插入的数据
for(j=1;j<i;j++)//找到要插入的位置
if(data[i]<data[j]) break;
if(j>=i) continue;//无需插入
for(int k=i-1;k>=j;k--)
data[k+1]=data[k];//后移
data[j]=data[0];//插入
}
二.希尔排序
希尔排序又称“缩小增量排序”,时间效率会高很多。话不多说,先看代码。
void InsertSort(int data[])//希尔排序
{
printf("希尔排序:\n");
//生成随机数并输出
for(int i=1;i<max;i++)
data[i]=rand()%100;
for(int i=1;i<max;i++)
printf("%3d",data[i]);
int i,j,d;
d=(max-1)/2;//折半取d
while(d>=1)
{
for(i=1;i<max-d;i++)//或者i=d+1;i<max;i++,那后面的j也要相应的变为,j=i-d;
{
j=i;
while(j>0)
{
if(data[j+d]<data[j])//如果后面的小,则交换
{
data[0]=data[j];
data[j]=data[j+d];
data[j+d]=data[0];
j=j-d;//继续往前比较
}
else j=0;//如果后面的较大,说明已经有序,直接退出while循环
}
}
printf("\n增量为%d的排序结果:\n",d);
for(int i=1;i<max;i++)
printf("%3d",data[i]);
d=d/2;
}
}
刚开始是生成随机数,就不用多说了。然后取增量d,增量的取法多种多样,不同的取法适合不同类型的问题,我们这里采用比较常见的折半取增量,d最后一次一定为1(最后一次直接插入排序一趟)。其他的看注释也就差不多了,本质上还是插入排序,只不过是隔几个数据排序。
三.其他插入排序
其他的插入排序方法也有很多,都不怎么常用,如:2路,表插等,有时间再写写吧。
ps:希尔排序的时间复杂度不一定是n^2,要看增量取法。