插入排序(希爾排序)

一.直接插入排序

在希爾排序之前,我們先來看一下比較簡單的直接插入排序。其算法思想主要是,將一個無序的數據插入到已經排好序的有序表中,從而得到一個數據量+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,要看增量取法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章