先贴上代码
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一直指在数组的最后位置)