有了插入排序的基础,希尔排序就很好理解了。
插入排序总是比较和移动相邻元素,但如果一个元素的位置需要移动很大的话就需要付出很大的代价。希尔排序对插入排序进行了简单而又有效的加速:使数组中任意间隔为h的元素都是有序的,即把数组中间任意一组隔为a的元素单独拿出来,它们都是有序的。当希尔排序中的h=1时,它就退化为插入排序了,这也是希尔排序的收尾工作。换一种方式叙述:希尔排序对于每个h,用插入排序将h个子数组独立排序。
希尔排序比插入排序更高效,排序初,由于h很大,所以每个子数组都很短,排序后的子数组都是有序的。排序到了后面,h越来越小,子数组中部分有序的数量越来越多。计算机科学家们给出了一个性能较好的h递增序列:h=3*h+1,但至今仍未找到性能最好的h序列。
看看逆序数组的排序过程:
h=13
7 19 18 17 16 15 14 13 12 11 10 9 8 20 6 5 4 3 2 1
7 6 18 17 16 15 14 13 12 11 10 9 8 20 19 5 4 3 2 1
7 6 5 17 16 15 14 13 12 11 10 9 8 20 19 18 4 3 2 1
7 6 5 4 16 15 14 13 12 11 10 9 8 20 19 18 17 3 2 1
7 6 5 4 3 15 14 13 12 11 10 9 8 20 19 18 17 16 2 1
7 6 5 4 3 2 14 13 12 11 10 9 8 20 19 18 17 16 15 1
7 6 5 4 3 2 1 13 12 11 10 9 8 20 19 18 17 16 15 14
h=4
3 6 5 4 7 2 1 13 12 11 10 9 8 20 19 18 17 16 15 14
3 2 5 4 7 6 1 13 12 11 10 9 8 20 19 18 17 16 15 14
3 2 1 4 7 6 5 13 12 11 10 9 8 20 19 18 17 16 15 14
3 2 1 4 7 6 5 13 12 11 10 9 8 20 19 18 17 16 15 14
3 2 1 4 7 6 5 13 12 11 10 9 8 20 19 18 17 16 15 14
3 2 1 4 7 6 5 13 12 11 10 9 8 20 19 18 17 16 15 14
3 2 1 4 7 6 5 13 12 11 10 9 8 20 19 18 17 16 15 14
3 2 1 4 7 6 5 9 12 11 10 13 8 20 19 18 17 16 15 14
3 2 1 4 7 6 5 9 8 11 10 13 12 20 19 18 17 16 15 14
3 2 1 4 7 6 5 9 8 11 10 13 12 20 19 18 17 16 15 14
3 2 1 4 7 6 5 9 8 11 10 13 12 20 19 18 17 16 15 14
3 2 1 4 7 6 5 9 8 11 10 13 12 20 19 18 17 16 15 14
3 2 1 4 7 6 5 9 8 11 10 13 12 20 19 18 17 16 15 14
3 2 1 4 7 6 5 9 8 11 10 13 12 16 19 18 17 20 15 14
3 2 1 4 7 6 5 9 8 11 10 13 12 16 15 18 17 20 19 14
3 2 1 4 7 6 5 9 8 11 10 13 12 16 15 14 17 20 19 18
此时的数组(红色子数组有序):
3 2 1 4 7 6 5 9 8 11 10 13 12 16 15 14 17 20 19 18
3 2 1 4 7 6 5 9 8 11 10 13 12 16 15 14 17 20 19 18
3 2 1 4 7 6 5 9 8 11 10 13 12 16 15 14 17 20 19 18
3 2 1 4 7 6 5 9 8 11 10 13 12 16 15 14 17 20 19 18
h=1
略
上代码:
public static void sort(int[] a){
int n=a.length;
int h=1;
while (h<n/3)
h=3*h+1;
while (h>=1){
for (int i=h; i<n; i++){
for (int j=i; j>=h&&(a[j]<a[j-h]); j-=h)
swap(a, j, j-h);
}
h/=3;
}//while
}//sort
用柱状图来感受一下希尔排序:
希尔排序的代码量很小,可以作为一般中小规模的排序算法使用。关于希尔排序更加详细的介绍可以自行百度。
BY DXH924
2018.10.26