先贴上代码
1 #include<stdio.h>
2 #define N 12
3 //length统计数组的长度 返回最后元素的下标
4 int length(int a [N]){
5 for(int i = 0;i<=N;i++){
6 if(a[i]==0) return i-1;
7
8 }
9 }
10 //打印输出数组元素
11 void show(int a[N]){
12 for(int i= 0;i<N;i++){
13 if(a[i]!=0) printf("%4d",a[i]);
14
15 }
16 }
17 //希尔排序 (插入排序升级版)
18 void shellsort(int a [N]){
19 int gap = length(a)/2 ;
20 do{
21 int temp=0;
22 for(int i = gap;i<=length(a);i++){
23 for(int j = i;j>=gap;j-=gap){
24 if(a[j-gap]>a[j]){
25 temp = a[j-gap] ;
26 a[j-gap]=a[j] ;
27 a[j]=temp;}
28 }
29 } printf("%d\n",gap); //打印输出每次循环时gap的数值 输出值依次为为4 2 1
30 gap/=2;
31 }while(gap!=0); //这里可以使用for循环也可以使用do while循环
32 }
33 int main(void){
34 int a [N] ={2,3,467,1,22,3,5,34,4,7} ; //手动生成数组a
35 printf("%d\n",length(a));
36 shellsort(a);
37 show(a); //输出 1 2 3 3 4 5 7 22 34 467 结果正确
38
39 return 0 ;
40 }
简单希尔排序算法需要注意的三个关键点在于gap值的选择,以及数组下标i,j和gap的位置关系,要保证程序在gap==1时算法退化成插入排序
以一个简单的数组 7 6 3 2 4 1为例循环开始时,gap简写为g,以括号表示g,i,j所在数字的位置,初始gap=3,数组下标初始值为0,用[]表示需要交换数值的两个元素,需要注意的是gap处在最外层循环,当i的循环结束时,gap的值才会改变
[7](j-g) 6 3 [2](g,i,j) 4 1 -->2 [6](j-gap) 3 7(g) [4](i,j) 1 -->2 4 [3](i,j) 7(g) 6 [1](i,j) //从这里第一次i循环结束,gap/2 =1 退化为简单的插入排序 -->[2](j-g) [4](g,i,j) 1 7 6 3 -->2 [4](g) [1](i) 7 6 3 --> [2](i-g) [1](g,i,j) 4 7 6 3 --> 1 2 4 7 6 3 依此类推-------->>> 1 2 4 6 7 3 ---->> 1 2 3 6 7 4 --> 1 2 3 4 6 7 (这三次迭代执行的都是j循环 i一直指在数组的最后位置)