一.希尔排序(Shell Sort)是插入排序的一种。是针对直接插入排序算法的改进。该方法又称缩小增量排序,因D.L.Shell于1959年提出而得名。
二.希尔排序的基本思想
1.先将整个待排记录序列分割成若干个子序列,子序列中进行直接插入排序,待整个序列“基本有序”时,再对全体记录进行一次直接插入排序。
2.基本有序:小的基本在前,大的基本在后,不大不小的基本在中间。
3.何为分割? :将相距某个“增量”的记录组成一个子序列,保证在子序列内部进行直接插入排序后得到的结果是基本有序,而不是局部有序,然后缩小“增量”组成新的子序列,再次进行以上操作,直至“增量”缩小到1,循环结束,排序也结束
三.希尔排序的核心
通过对希尔排序思想的介绍,我们可以发现希尔排序的核心就是通过“增量”去进行分组,然后逐渐减小“增量”重新分组,直至增量减小到1,排序也就完成了,所以“增量”怎么设置呢?
不好意思现在科学家也没有给出最好的求解增量的方法,同学们想看有关资料可以去问问度娘。只是尽量将“增量”设置为一组素数
在下面的代码中,我们采用增量的求法为 increase=increase/3+1;
四.希尔排序的图文解释
上面文字性的概念大家尽量取理解,没理解也没有关系,最硬核的图文解释来了,嘿嘿!我们开始吧
我们依然以“8,5,4,3,2,1,6,7”这组序列进行举例
在代码中进入do循环,我们首先求得增量increase=3,所以进入for循环,第一次for循环中我们要比较a[3]与a[3-3]的值
经比较a[0]>a[3],所以对其进行直接插入排序得到下图
第一次for循环结束,i++,进入第二次for循环,此时我们比较a[4]与a[4-3]
经比较a[1]>a[4],所以对其进行直接插入排序得到下图
第二次for循环结束,i++,进入第三次for循环,此时我们比较a[5]与a[5-3]
经比较a[2]>a[5],所以对其进行直接插入排序得到下图
第三次for循环结束,i++,进入第四次for循环,此时我们比较a[6]与a[6-3]
经比较a[3]>a[6],所以对其进行直接插入排序得到下图
第四次for循环结束,i++,进入第五次for循环,此时我们比较a[7]与a[7-3]
经比较a[4]<a[7],所以不交换,现在序列的顺序为3,2,1,6,5,4,8,7,小的在前,大的在后,不大不小在中间。数列整体向着
基本有序发展,此时do-while循环进入第二次,求得增量increase=2,在进行以上步骤,直至increase=1结束排序。这两个过程留给读者去实现,过程非常简单,大家一定能做到
下面就是c语言实现过程了请大家认真参考
#include <stdio.h>
void shell(int* r,int len)
{
int i,j ;
int temp;
int increase=len;
do{
increase=increase/3+1;
for(i=increase;i<=len;i++)
{
if(r[i]<r[i-increase])
{
temp=r[i];
for(j=i-increase;j>=0&&temp<r[j];j-=increase)//直接插入排序
r[j+increase]=r[j];
r[j+increase]=temp;
}
}
}while(increase>1);
}
void main(){
int i;
int a[8] = { 8, 5, 4, 3, 2, 1, 6, 7 };
printf("before:{");
for(i = 0; i < 8; i++){
printf("%d ",a[i]);
}
printf("}\n");
shell(a,8);
printf("after:{");
for(i=0; i<8; i++){
printf("%d ",a[i]);
}
printf("}\n");
}
希尔排序作为直接插入排序的改进,性能优于直接插入排序,但当文件初态基本有序时直接插入排序所需的比较和移动次数均较少。
同时算法中选区的增量序列不同,其算法执行时间也不同。目前为止希尔排序最优的时间复杂度是O(N^1.3)
最后说明希尔排序不是一个稳定的排序算法