【筆記】希爾排序

Time-space發表於2017-11-03

  插入排序:將待排序元素分為已排序子集和未排序子集,一次從未排序子集中的一個元素插入已排序子集中,使已排序自己仍然有序;重複執行以上過程,指導所有元素都有序為止。

  希爾排序又稱為縮小增量排序,它也是一種屬插入排序類的方法,但在事件效率上較前述集中排序方法都有較大的改進。
  從對直接插入排序的分析得知,其演算法時間複雜度為O(n2)

O(n^2)
,但是若待排記錄序列為“正序”時,其時間複雜度可提高至O(n)
O(n)
。由此可設想,若待排記錄序列按關鍵字基本有序,即序列中具有下列特性

L.data[i].key<max1j<i{L.data.key}
L.data[i].key<max_{1 \leq j < i} \{L.data.key\}
的記錄較少時,直接插入排序的效率就可大大提高,從另一方面來看,由於直接插入排序的演算法簡單,則在n值很小時效率也比較高。希爾排序正是從這兩點分析出發對直接插入排序進行改進得到的一種排序方法。

  基本演算法思想:先將整個待排記錄序列分割成為若干子序列分別進行直接插入排序,待整個序列中的記錄基本有序時,再對全體記錄進行一次直接插入排序。


這裡寫圖片描述

  從上述排序過程可見,希爾排序的一個特點是:子序列的構成不是簡單地逐段分割,而是將相隔某個增量的記錄組成一個子序列。如上圖中,第一趟排序時的增量為5,第二趟排序時的增量為3,由於在前兩趟的插入排序中記錄的關鍵字是和同一子序列中的前一個記錄的關鍵字進行比較,因此關鍵字較小的記錄就不是一步一步地往前挪動,而是跳躍式地往前移,從而使得在進行最後一趟增量為1的插入排序時,序列已基本有序,只要作記錄的少量比較和移動即可完成排序,因此希爾排序的時間複雜度較直接插入排序低。

  • 型別定義
#include<stdio.h>
#include<stdlib.h>
#define MaxSize 100
typedef int KeyType;
typedef struct /*資料元素型別定義*/
 {
    KeyType key;/*關鍵字*/
}DataType;
typedef struct /*順序表型別定義*/
 {
    DataType data[MaxSize];
    int length;
}SqList;
  • 希爾排序函式
void ShellInsert(SqList *L,int c)
/*對順序表L進行一次希爾排序,c是增量*/
{
    int i,j;
    DataType t;
    for(i=c+1;i<=L->length;i++)             /*將距離為c的元素作為一個子序列進行排序*/
    {
        if(L->data[i].key<L->data[i-c].key)     /*如果後者小於前者,則需要移動元素*/
        {
            t=L->data[i];
            for(j=i-c;j>0&&t.key<L->data[j].key;j=j-c)
                L->data[j+c]=L->data[j];
            L->data[j+c]=t;             /*依次將元素插入到正確的位置*/
        }
    }
}
void ShellInsertSort(SqList *L,int delta[],int m)
/*希爾排序,每次呼叫演算法ShellInsert,delta是存放增量的陣列*/
{
    int i;
    for(i=0;i<m;i++)            /*進行m次希爾插入排序*/
    {
        ShellInsert(L,delta[i]);
    }
}
  • 主函式
void InitSeqList(SqList *L,DataType a[],int n)
/*順序表的初始化*/
{
    int i;
    for(i=1;i<=n;i++)
    {
        L->data[i]=a[i-1];
    }
    L->length=n;
}
void DispList(SqList L,int n)
/*順序表的輸出*/
{
    int i;
    for(i=1;i<=n;i++)
        printf("%4d",L.data[i].key);
    printf("\n");
}

void main()
{
    DataType a[]={78,29,45,10,80,21,55,3,60,32};
    int delta[]={5,3,1};
    int n=10,m=3;
    SqList L;
    InitSeqList(&L,a,n);
    printf("[排序前]          ");
    DispList(L,n);
    ShellInsertSort(&L,delta,m);
    printf("[希爾排序結果]    ");
    DispList(L,n);
}
  • 測試結果

這裡寫圖片描述

相關文章