思想
希尔排序是对简单插入排序算法的一个升级,它的思路就是将原有大量数据记录分割成如干个子序列,再分别对子序列进行插入排序,当整个序列基本有序时,再对全体记录做一次插入排序。
基本有序:就是小的基本在前面,不大不小基本在中间,大的基本在后面。
我们上面提到了将整序列进行分割,那么如何分割将是关键,按顺序分割显然就不合适了,比如我们现在有序列是{9,1,5,8,3,7,4,6,2},现在将它分成三组,{9,1,5} ,{8,3,7}, {4,6,2} ,哪怕将它们各自排序排好了,变成{1,5,9} , {3,7,8},{2,4,6},再合并它们成{1,5,9,3,7,8,2,4,6},此时,这个序列还是杂乱无序,谈不上基本有序。所以我们需要采取“跳跃分割”策略:将相距某个‘增量'的记录组成一个子序列,这样才能保证在子序列内分别进行直接插入排序后得到的结果是基本有序而不是局部有序。
排序过程
以数组 int[] test = {51, 46, 20, 18, 65, 97, 82, 30, 77, 50}为例,这里我选取增量increment = increment / 3;
第一回合:初始增量为test.length /3 = 3
第二回合:增量为1,此时已经是基本有序了,直接进行插入排序达到最终有序
代码
public static void shellSort(int[] test) {
int j = 0;//记录位置
//跳跃分割即是定义一个增量,将相距这个增量的记录组成子序列,并分别进行简单插入排序
for(int increment = test.length / 3;increment > 0;increment = increment/3) {
for (int i = increment; i < test.length; i++) {
int temp = test[i];//定义一个哨兵
for (j = i - increment; j >= 0 && test[j] > temp; j-=increment) {//前面的数大于后面的数
test[j+increment] = test[j];//往后移动
}
test[j+increment] = temp;
}
System.out.println(Arrays.toString(test));
}
}