/*
* 希尔排序
* 希尔排序就是将一个数组按照分段因子来计算出最大分段数,将一个数组根据最大分段数进行分段,在分段元素中进行排序,然后依次减小分段数,直到分段数为1的时候,排序完便结束
* 例如数组int[] a = {4,2,8,9,5,7,6,1,3,10,13}; 设置分段因子为3
* 那么分段数的公式就为h = 3 * h +1. 可以得到分段数为1,4,13,40...。由于数组的最大长度是 11,最大分段数必须小于数组的长度,
* 所以这里的最大分段数为4,针对于数组a,下面来分析一下希尔排序具体是如何排序的
* 最大分段数是4,那么这个数组被分成了[4(0),5(4),3(8)],[2(1),7(5),10(9)],[8(2),6(6),13(10)],[9(3),1(7)],注意这里的分组是逻辑上的分组,不是物理上的分组。
* 然后在分组内进行插入排序,通过分段数为4的一轮排序之后得到的结果为[3(0),4(4),5(8)],[2(1),7(5),10(9)],[6(2),8(6),13(10)],[1(3),9(7)],
* 那么得到的数组是int[] a = {3,2,6,1,4,7,8,9,5,10,13};
* 分段数为4的排序完了之后,再需要使用分段数1进行排序
* 对数组进入插入排序,
* 最终得到的结果是[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 13]
* 代码示例如下:
*/
public class RecursiveHillSort {
public static void main(String[] args) {
int[] a = {4,2,8,9,5,7,6,1,3,10,13};
hillSort(a);
}
private static void hillSort(int[] a){
int length = a.length;
//分段数
int h = 1;
while(h <= length/3){
//计算出最大分段数,分段因子为3
h = 3*h +1;
}
//当分段数为0的时候结束循环
while(h>0){
//下面进行分段式插入排序
for(int i = h; i < length; i++){
//保存插入的标志位
int cmp = i;
//保存标志位数据
int temp = a[cmp];
while((cmp-h) >= 0){
if(temp < a[cmp-h]){
a[cmp] = a[cmp-h];
cmp = cmp -h;
}else{
break;
}
}
a[cmp] = temp;
}//一趟排序结束
System.out.println(Arrays.toString(a));
//减小分段数,再进行排序
h = (h-1)/3;
}
}
}
//执行结果如下所示:
[3, 2, 6, 1, 4, 7, 8, 9, 5, 10, 13]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 13]