1.希尔排序的产生
希尔排序是基于插入排序的,插入排序步长为1的,而插入排序的步长是计算出来的。(学习希尔排序之前需要了解插入排序)。
2.插入排序的缺陷
步长为1的插入排序,必须得移动多次,举个栗子,假如一个很小的数据在考右侧的位置上,那么要讲该数据排序到正确的位置上,则所有中间数据都需要向右移动一次。
3.希尔排序的优点
希尔排序通过加大插入排序中元素之间的间隔(步长),并对这些间隔的元素进行排序,从而使得数据可以大幅度的移动,当完成该间隔的排序后,希尔排序会减少数据的间隔再进行排序,依次进行下去。
4.排序过程:
待排序数组:48, 37 ,64, 96, 75, 12, 26, 48, 54, 03
步骤一:选一个小于n(就是你的数组长度)的数字(比如选5),然后按照这个数来分组,即第一个和隔5个数之后的数字分为一组。在这个例子里:48和隔个5个数的12为一组,因为12后面不够5个数了,所以这个分组就到这了。
分组情况:
步骤二:将第一开始的分组的数字以直接插入的方式,按照从小到大的排序(也可以按照从大到小来)
12,26,45,54,03,48,37,64,98,75
步骤三:由于第二部进行了排序,在这个基础上,再一次选一个小于 d1的数字,d2,以这个数字分组,这次以d2=3举例
因此,第二次的分组情况如下:
步骤四:将刚刚分完组的数字,进行组内排序,还是以直接插入排序,所以排序之后结果是下面的情况:
12,03,45,37,26,48,54,64,75
步骤五:这次还要选一个数字d3作为分组的标准,第一,二两次分别用的5,3,这次用d3=1。也就是说这次可以直接整体用直接插入排序了。
步骤六:直接插入排序结果为:03,12,26,37,45,48,54,64,75
5.步长的计算
步长h的初始值为1,通过公式:h=3*h+1来循环计算,知道该间隔大于数组的大小时停止。
,h取值为(1,4,13,40…)
6.步长减少计算
通过公式:h=(h-1)/3
7.讲解代码
public static void sort(long[] arr) {
//初始化一个间隔
int h = 1;
//计算最大间隔
while(h < arr.length / 3) {
h = h * 3 + 1;
}
while(h > 0) {
//进行插入排序
long tmp = 0;
for(int i = h; i < arr.length; i++) {
tmp = arr[i];
int j = i;
while(j > h - 1 && arr[j - h] >= tmp) {
arr[j] = arr[j - h];
j -= h;
}
arr[j] = tmp;
}
//减小间隔
h = (h - 1) / 3;
}
}
}