1.希尔排序思想
(1)希尔排序是直接插入排序算法的一种更高效的改进版本;
(2)方法一般是:先取一个小于n的整数d1作为第一个增量,把文件的全部记录分组,所有距离为d1的倍数的记录放在同一个组中。先在各组内进行直接插入排序;然后,取第二个增量d2 < d1重复上述的分组和排序,直至所取的增量 =1( < …< d2< d1),即所有记录放在同一组中进行直接插入排序为止。
(3)之所以采用希尔排序,是因为:
a)插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率。
b)但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位。
2.希尔排序详细分析(以递减为例)
设需排序的数组 a={34,23,12,43 , 22 , 11 , 45 , 32,33 , 11}
(1)首先设 d = a.length/2=5,则序列a分为5组,分别为{34,11}、{23、45}、{12、32}、{43、33}、{22、11};
(2)对上述每组数据分别进行直接插入排序,排序后序列a为{34,45,32,43,22,11,23,12,33,11};
(3)将增量d减小一半,即 d = d/2 = 2,则序列a分为两组,分别为{34,32,22,23,33}、{45,43,11,12,11};
(4)对上述两组数据分别进行直接插入排序,排序后序列a为{34,45,33,43,32,12,23,11,22,11};
(5)再将增量d减小一般,此时d=1,进行最后一次直接插入排序,排序后序列a为{45,43,34,33,32,23,22,12,11,11}。
注:以上对于增量d的选择不是必须按照上述的固定选择,但是它必须从大到小,单调递减,且最后一趟一定是1。
3.算法性能
(1)平均时间复杂度:希尔排序的时间复杂度和其增量序列有关系,这涉及到数学上尚未解决的难题;不过在某些序列中复杂度可以为O(n1.3);
(2)空间复杂度:O(1)
(3)稳定性:不稳定
4.算法实现(java)
public static int[] ShellSort(int[] a){
int n = a.length;
if(n<=1) return a;
int d = n;
while(d>1){
d = d/2;
for(int i =0; i<d; i++){ //对每组数据进行插入排序
for(int j = i+d; j<n ;j=j+d){ //对其中一组数据进行插入排序
if(a[j]>a[j-d]){ //寻找一组数据中每个数据的插入位置
int temp = a[j];
int k = 0;
for(k = j - d; k >=0 && temp > a[k]; k = k-d){
a[k+d] = a[k];
}
a[k+d] = temp;
}
}
}
}
return a;
}