基本思想
先將整個待排序的記錄序列分割成爲若干子序列分別進行直接插入排序,待整個序列中的記錄“基本有序”時,再對全體記錄進行依次直接插入排序。
操作方法
- 選擇一個增量序列t1,t2,…,tk,其中ti>tj,tk=1;
- 按增量序列個數k,對序列進行k 趟排序;
- 每趟排序,根據對應的增量ti,將待排序列分割成若干長度爲m 的子序列,分別對各子表進行直接插入排序。僅增量因子爲1 時,整個序列作爲一個表來處理,表長度即爲整個序列的長度。
希爾排序的示例:
算法實現
我們簡單處理增量序列:增量序列d = {n/2 ,n/4, n/8 …..1} n爲要排序數的個數
即:先將要排序的一組記錄按某個增量d(n/2,n爲要排序數的個數)分成若干組子序列,每組中記錄的下標相差d.對每組中全部元素進行直接插入排序,然後再用一個較小的增量(d/2)對它進行分組,在每組中再進行直接插入排序。繼續不斷縮小增量直至爲1,最後使用直接插入排序完成排序。
#include<stdio.h>
//直接插入排序
void shellInsertSort(int r[],int n,int dk){
int i;
for(i=dk;i<n;i++){
if(r[i]<r[i-dk]){ //若第i個元素大於i-dk(dk是增量,直接插入排序的增量是1)元素,直接插入。小於的話,移動有序表後插入
int j = i-dk;
int x = r[i];//複製爲哨兵,即存儲待排序元素
while(x<r[j] && j>=0){//查找在有序表的插入位置
r[j+dk] = r[j];
j = j - dk; //元素後移
}
r[j+dk] = x; //插入到正確位置
}
}
}
//希爾排序(先按增量d(n/2,n爲要排序數的個數進行希爾排序 )
void shellSort(int r[],int n){
int dk;
dk = n/2;
while(dk>=1){
shellInsertSort(r,8,dk);
dk = dk/2;
}
}
//打印
void print(int r[],int n){
int i;
for(i=0;i<n;i++){
printf("%3d",r[i]);
}
printf("\n");
}
int main(){
int a[8] = {3,1,5,7,2,4,9,6};
printf("排序前:\n");
print(a,8);
printf("排序後:\n");
//shellInsertSort(a,8,1); //直接插入排序
shellSort(a,8); //希爾插入排序
print(a,8);
return 0;
}