插入排序(希尔排序)

一.直接插入排序

在希尔排序之前,我们先来看一下比较简单的直接插入排序。其算法思想主要是,将一个无序的数据插入到已经排好序的有序表中,从而得到一个数据量+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,要看增量取法。

猜你喜欢

转载自blog.csdn.net/qq_41024819/article/details/80506738
今日推荐