希尔排序也称为缩小增量排序,是插入排序算法的一种改进版。
希尔排序应该是最难的排序了
希尔排序的诞生是由于插入排序在处理大规模数组的时候会遇到需要移动太多元素的问题。
希尔排序的思想是将一个大的数组“分而治之”,将一个大的数组划分为若干个小的数组。以 gap (间隔)来划分,比如数组 [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ] ,如果以间隔 gap = 2划分,可以划分为 [ 1 , 3 , 5 , 7 ] 和 [ 2 , 4 , 6 , 8 ] 两个数组;对应的,若间隔 gap = 3 ,则划分的数组为: [ 1 , 4 , 7 ] 、 [ 2, 5 , 8 ] 、 [ 3 , 6 ] 。然后分别对这些子数组进行正统的插入排序,排序好后将数组回收到大数组里,再减少间隔 gap 的值重复进行之前的操作,直到间隔 gap = 1时,此时子数组只有一个,就是整个大数组,此时其实都快排好序了,在对这唯一的子数组进行最后一次插入排序的时候,移动的数会很少很少,从而解决了插入排序在处理大规模数组时较多移动次数的问题。
初始数组:[ 26 , 19 , 7 , 37 , 27 , 57 , 67 , 99 , 87 , 17 ]
第一次:
初次计算间隔 gap = 10 / 2 = 5
( 26 走五步是57,以此类推 )
26 19 7 37 27
57 67 99 87 17
进行列排序( 比如,26和57是一列,以此类推 )
26 19 7 37 17
57 67 99 87 27
按行取回放入大数组里:[ 26 , 19 , 7 , 37 , 17 , 57 , 67 , 99 , 87, 27 ]
第二次:
gap = 5 / 2 = 2
( 26 走两步是7,以此类推 )
26 19
7 37
17 57
67 99
87 27
进行列排序( 比如,26、7、17、67、87 是一列,以此类推 )
7 19
17 27
26 37
67 57
87 99
按行取回放入大数组里:[ 7 , 19 , 17 , 27 , 26 , 37 , 67 , 57 , 87 , 99 ]
第三次:
gap = 2 / 2 = 1
( 7 开始一步一步走 )
7
19
17
27
26
37
67
57
87
99
进行列排序
7
17
19
26
27
37
57
67
87
99
按行取回放入大数组里:[ 7 , 17 , 19 , 26 , 27 , 37 , 57 , 67 , 87 , 99 ]
总结:其实很有节奏和规律,不算复杂。
public <T extends Comparable<T>> void shellSorting(T[] array) {
int len = array.length;
int i, j, gap;
// 逐渐减小步长
for (gap = len / 2; gap > 0; gap /= 2) {
// 布置行数据
for (i = 0; i < gap; i++) {
// 布置列数据
for (j = gap; j < len; j += gap) {
if (array[j - gap + i].compareTo(array[j + i]) > 0) {
T temp = array[j - gap + i];
array[j - gap + i] = array[j + i];
array[j + i] = temp;
}
}
}
}
}
public static void main(String args[]) {
Integer[] object = {26, 19, 7, 37, 27, 57, 67, 99, 87, 17};
System.out.println("\n希尔排序\n");
ShellSort shellSorting = new ShellSort();
shellSorting.shellSorting(object);
System.out.println("\n希尔排序\n");
for (int i : object) {
System.out.print(i + " ");
}
}