內部排序->插入排序->希爾排序
阿新 • • 發佈:2018-07-25
關鍵字 stdio.h style http hide ron [] The png
文字描述
希爾排序又稱縮小增量排序,也屬於插入排序類,但在時間效率上較之前的插入排序有較大的改進。
從之前的直接插入排序的分析得知,時間復雜度為n*n, 有如下兩個特點:
(1)如果待排序記錄本身就是“正序”時, 其時間復雜度可減少為n。
(2)當待排序記錄數很小時,直接插入排序的效率也比較高;
希爾排序正是從這兩點分析出發對直接插入排序進行了改進。它的基本思想是:先將整個待排記錄序列分割成為若幹個子序列分別進行直接插入排序,待整個序列中的記錄“基本有序“時,再對全體記錄進行一次直接插入排序。
示意圖
算法分析
希爾排序的空間復雜度是所取增量數組的個數加1。
希爾排序的時間復雜度分析是一個復雜的問題,因為它的時間是所取”增量”序列的函數,這涉及一些數學上尚未解決的難題。但是在大量的前人做的實驗基礎上推出:當n在某個特定範圍內,希爾排序所需的比較和移動次數均約為n^(1.3), 當n無窮大時,可減少到n(log2n)^2。
增量序列可以有各種取法,但是需註意:應使增量序列中的值沒有除1之外的公因子,並且最後一個增量值必須等於1。
代碼實現
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 #define DEBUG 5 6 #define希爾排序EQ(a, b) ((a) == (b)) 7 #define LT(a, b) ((a) < (b)) 8 #define LQ(a, b) ((a) <= (b)) 9 10 #define MAXSIZE 20 11 typedef int KeyType; 12 typedef int InfoType; 13 typedef struct{ 14 KeyType key; 15 InfoType otherinfo; 16 }RedType; 17 18 typedef struct{ 19 RedType r[MAXSIZE+1]; 20 int length; 21 }SqList; 22 23 //依次打印順序表L中的下標和關鍵字 24 void PrintList(SqList L){ 25 int i = 0; 26 printf("下標值:"); 27 for(i=0; i<=L.length; i++){ 28 printf("[%d] ", i); 29 } 30 printf("\n關鍵字:"); 31 for(i=0; i<=L.length; i++){ 32 printf(" %-3d", L.r[i].key); 33 } 34 printf("\n其他值:"); 35 for(i=0; i<=L.length; i++){ 36 printf(" %-3c", L.r[i].otherinfo); 37 } 38 printf("\n\n"); 39 return ; 40 } 41 42 /* 43 *對順序表L作一趟希爾插入排序。本算法和一趟直接插入 44 *排序相比,作了以下修改: 45 * 1。前後記錄位置的增量為dk, 而不是1 46 * 2。r[0]只是暫存單元,不是哨兵 47 */ 48 void ShellInsert(SqList *L, int dk) 49 { 50 int i = 0, j = 0; 51 for(i=dk+1; i<=L->length; ++i){ 52 //需將L->r[i]插入有序增量子表 53 if(LT(L->r[i].key, L->r[i-dk].key)){ 54 //暫存在L->r[0] 55 L->r[0] = L->r[i]; 56 for(j=i-dk; j>0&<(L->r[0].key, L->r[j].key); j-=dk){ 57 //記錄後移,找插入位置 58 L->r[j+dk] = L->r[j]; 59 } 60 //插入位置找到,插入數據 61 L->r[j+dk] = L->r[0]; 62 } 63 } 64 } 65 66 //按照增量序列dlta[0..t-1]對順序表L作希爾排序 67 void ShellSort(SqList *L, int dlta[], int t) 68 { 69 #ifdef DEBUG 70 printf("輸入數組:\n"); 71 PrintList(*L); 72 #endif 73 int k = 0; 74 for(k=0; k<t; k++){ 75 //一趟增量為dlta[k]的插入排序 76 ShellInsert(L, dlta[k]); 77 #ifdef DEBUG 78 printf("第%d趟增量%d希爾排序後:\n", k, dlta[k]); 79 PrintList(*L); 80 #endif 81 } 82 } 83 84 int main(int argc, char *argv[]) 85 { 86 if(argc < 2){ 87 return -1; 88 } 89 SqList L; 90 int i = 0; 91 for(i=1; i<argc; i++){ 92 if(i>MAXSIZE) 93 break; 94 L.r[i].key = atoi(argv[i]); 95 L.r[i].otherinfo = ‘a‘+i-1; 96 } 97 L.length = (i-1); 98 L.r[0].key = 0; 99 L.r[0].otherinfo = ‘0‘; 100 //希爾排序的增量 依次取9 5 3 1 101 int dlta[4] = {9,5,3,1}; 102 //調用希爾排序算法 103 ShellSort(&L, dlta, 4); 104 return 0; 105 }
運行
內部排序->插入排序->希爾排序