一、基本思想
希尔排序(Shell Sort)是插入排序的一种,也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。
其处理过程为:对一组无序的数列,选择一个增量,即 gap = array.length / 2,以此增量进行第一趟数据分组与排序,然后缩小增量,继续以 gap = gap / 2 的方式进行分组和排序;每趟排序,根据对应的增量,将待排序列分割成若干长度为 m 的子序列,分别对各子序列进行直接插入排序。当增量因子为 1 时,整个序列作为一个组来处理,对其进行直接插入排序的结果即为有序序列。
二、举例分析
假设有一序列 8,6,3,2,5,7,1,4,初始增量 gap = length / 2 = 4,则整个序列被分为 4 组,[8, 5], [6, 7], [3, 1], [2, 4],如下图(颜色相同的为一组):
对这 4 组分别进行直接插入排序,结果如下:
缩小增量 gap = 4 / 2 = 2,数组被分为 2 组,[5, 1, 8, 3], [6, 2, 7, 4],如下图:
对这两组分别进行直接插入排序,结果如下:
缩小增量 gap = 2 / 2 =1,整个数组为一组,[1, 2, 3, 4, 5, 6, 8, 7],此时,整个数组已基本有序,只需简单微调就可得到有序序列。
三、代码实现
public int[] shellSort(int[] sourceArray){
int[] array = Arrays.copyOf(sourceArray, sourceArray.length);
int length = array.length;
int gap = length / 2;
while(gap > 0){// gap <= 0时,就不用再分组了,
// 对每个分组进行插入排序
// 注:为什么从 i = gap开始,单纯的插入排序时,先将array[0],看做有序序列,然后
// 把第二个元素到最后一个元素当成是未排序序列,扫描未排序序列并进行插入。用gap分组后,
// array[0]作为有序序列,第二个元素为array[gap].
for (int i = gap; i < array.length; i++) {
int temp = array[i];
int j = i - gap;
while(j >= 0 && array[j] < temp){// 小的往后移,降序
array[j + gap] = array[j];
j = j - gap;
}
array[j + gap] = temp;
}
gap = gap / 2;
}
return array;
}