希尔排序是插入排序的一种优化。
什么是希尔排序:
希尔排序又称缩小增量法。 其思想是将整个待排元素序列分割成若干个(gap个)子序列(每个序列的每个元素之间的间距(gap)是相同的),分别对这些子序列进行直接插入排序,然后依次缩减gap再进行排序,待整个序列中的元素基本有序时,再对整体待排元素进行一次直接插入排序。
直接插入排序有一个特性是,整个待排元素越趋于有序状态,直接插入排序的效率越高。希尔排序每一次分割排序会将整个待排元素变得趋于有序,所以每一次排序的效率会越来越高。
gap的值,不是用来确定整个待排元素被分成几组。很多小伙伴会疑惑,假如数组长度是11,gap为5,不就多出来一个元素吗。
同一组中,每个元素的步长也是5,所以下标为10的元素就放在了黑色线标记出来的第一组中。
在写代码时,不要想着先把第一组的数据变成有序数组,再去找第二组的数据变成有序数组。
我们可以从下标为5(gap)的数据向后走,用gap找到它的前一个组员。
public static void shell(int[] array, int gap){
for(int i = gap; i < array.length; i++){
int tmp = array[i];
int j = i - gap;
for(; j >= 0; j -= gap){
if(array[j] > tmp){
array[j+gap] = array[j];
}else {
break;
}
}
array[j+gap] = tmp;
}
}
剩下的就是用直插法的思路,假如前一个数据大于当前tmp,也就是i下标的数据。那就把前一个数据放到i(也就是 j + gap)下标来。继续向前直到找到适合插入tmp的位置。
public static void shellSort(int[] array){
int gap = array.length;
while(gap > 1){
gap /= 2;
shell(array, gap);
}
}
gap不一定是每次都除以2,也有人选择 gap = gap / 3 + 1.
希尔排序是不稳定的,上上图可以看到带下划线的5最后排到了不带下划线的5前面。