前端設計模式總結
阿新 • • 發佈:2020-11-14
希爾排序是插入排序的一種,又叫縮小增量排序,也是對直接插入排序的一種優化,下面是插入排序的一些特徵:
- 時間複雜度不確定,看具體實現,依賴於增量序列函式,本文實現的時間複雜度為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 }