1. 程式人生 > 實用技巧 >前端設計模式總結

前端設計模式總結

希爾排序是插入排序的一種,又叫縮小增量排序,也是對直接插入排序的一種優化,下面是插入排序的一些特徵:

  • 時間複雜度不確定,看具體實現,依賴於增量序列函式,本文實現的時間複雜度為O(n^2),若步長選取為 2^k+1, ..., 5, 3, 1 其時間複雜度為 O(n1.5),當n在某個特定範圍時,有些實現可以達到O(n1.3)
  • 空間複雜度,最好最壞平均都為:O(1)
  • 是否穩定:不穩定

每次排序,資料都會變得更加有序

希爾排序的基本思想:先將待排序表每隔一定距離取一個數據,形成一個子表,整個表化為許多子表,然後對每個子表分別進行直接插入排序,步長越來越小,最後為1時,對錶整個表進行一次直接插入排序。

有人可能會覺得這不是簡單問題複雜化嗎?並不是,因為直接插入排序演算法適用於基本有序資料量不大的排序表,適用於的意思就是更快,所以可以利用這兩個特性對直接插入排序進行優化,將一個子表變成多個子表,就是在縮小資料量,子表有序後,整個表就更加有序了。

子表選取例子:原表L(1,2,3,4,5,6,7,8,9)有九個元素,步長 dk 取 9/2 即 4,得到 4 個子表 L1(1,5,9), L2(2,6), L(3,7), L(4,8)

下面是一種希爾排序的程式碼,增量選取為 n/2, n/4, ..., 2, 1:

/**
* arr 陣列首地址
* len 陣列長度
*/
void shell_sort(int *arr, int len)
{
    int i, j;
    int dk;     // 記錄步長
    for (dk=len/2; dk>=1; dk>>=1) { // 步長變化
        for (i=dk; i<len; i++) {
            if (arr[i] < arr[i-dk]) {
                int temp = arr[i];
                for (j=i-dk; j>=0 && temp<arr[j]; j-=dk)
                    arr[j+dk] = arr[j];
                arr[j+dk] = temp;
            }//if
        }//for
    }//for
}

測試程式碼,可直接複製後編譯執行:

#include <stdio.h>

void show(int *arr, int len);
void insert_sort(int *arr, int len);

int main()
{
    int len = 7;
    int arr[] = {7, 10, 11, 9, -8, 2, 27};
    insert_sort(arr, len);
    show(arr, len);
    return 0;
}

/**
* arr 陣列首地址
* len 陣列長度
*/
void show(int *arr, int len)
{
    int i;
    for (i=0; i<len; i++) {
        printf("%4d", arr[i]);
    }
    printf("\n");
}

/**
* arr 陣列首地址
* len 陣列長度
*/
void shell_sort(int *arr, int len)
{
    int i, j;
    int dk;     // 記錄步長
    for (dk=len/2; dk>=1; dk>>=1) { // 步長變化
        for (i=dk; i<len; i++) {
            if (arr[i] < arr[i-dk]) {
                int temp = arr[i];
                for (j=i-dk; j>=0 && temp<arr[j]; j-=dk)
                    arr[j+dk] = arr[j];
                arr[j+dk] = temp;
            }//if
        }//for
    }//for
}