一.希尔排序思想:
希尔排序也是一种插入排序方法,实际上是一种分组插入方法。先取定一个小于n的整数d1作为第一个增量,把表的全部记录分成d1个组,所有距离为d1的倍数的记录放在同一个组中,在各组内进行直接插入排序;然后,取第二个增量d2(<d1),重复上述的分组和排序,直至所取的增量dt=1(dt<dt-1<…<d2<d1),即所有记录放在同一组中进行直接插入排序为止。
例如:将 n 个记录分成 d 个子序列:
{ R[0], R[d], R[2d],…, R[kd] }
{ R[1], R[1+d], R[1+2d],…,R[1+kd] }
…
{ R[d-1],R[2d-1],R[3d-1],…,R[(k+1)d-1] }
这个是排序过程每次按增量分为一组,在组内排好序;理论说多了有点晕,来点实际例子:
例如:
数据未排序:[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
1.取增量d为排序个数一半:10/2=5
距离为5的数据分为一组,共5组[10,5],[9,4],[8,3],[7,2],[6,1]
分组排序[5,10],[4,9],[3,8],[2,7],[1,6],将分组数据复原到数组中
d=5:[5, 4, 3, 2, 1, 10, 9, 8, 7, 6]
2.增量递减一半:5/2=2
距离为2的数据分为一组,共2组[5,3,1,9,7],[4,2,10,8,6]
排序为[1,3,5,7,9] [2,4,6,8,10],将分组数据复原到数组中
d=2:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
3.增量递减一半:2/2=1
d=1:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
直到增量递减到1为止,增量大小视情况而定,分组排序时用的是插入算法,当然也可以选用适用排序算法。
我认为希尔排序是对插入排序的一种优化。
二、时间复杂度。
最好情况:由于希尔排序的好坏和步长d的选择有很多关系,因此,目前还没有得出最好的步长如何选择(现在有些比较好的选择了,但不确定是否是最好的)。所以,不知道最好的情况下的算法时间复杂度。最坏情况下:O(N*logN),最坏的情况下和平均情况下差不多。
平均情况下:O(N*logN)
三、稳定性。
由于多次插入排序,我们知道一次插入排序是稳定的,不会改变相同元素的相对顺序,但在不同的插入排序过程中,相同的元素可能在各自的插入排序中移动,最后其稳定性就会被打乱,所以shell排序是不稳定的。(有个猜测,方便记忆:一般来说,若存在不相邻元素间交换,则很可能是不稳定的排序。)四、与插入算法对比
五、源码
public void sort (int array[],int n)
{
int i=0,j=0,temp=0;
int d=n/2; /*初始增量*/
while (d>0){
for (i=d;i<n;i++){
//分组排序,距离是d的为一组
for(j=i-d;j>=0 && array[j] > array[j+d];j=j-d){
temp=array[j];
array[j]=array[j+d];
array[j+d]=temp;
}
}
//System.out.println("d="+d+Arrays.toString(array));
d=d/2; /*增量递减*/
}
}