又称缩小增量排序。
先选定一个整数gap(动态步长),将待排序的数据中所有记录按gap分组。所有距离为gap的数据放在同一组,将组内元素排序,然后不断缩小gap的大小直到变为1,当gap变为1时,整个数组已经近乎有序(直接插入排序最好的情况),调用普通插入排序统一排序即可。
- 希尔排序是对直接插入排序的优化。
- 当gap > 1时都是预排序,目的是让数组更接近于有序。当gap == 1时,数组已经接近有序了,这样就会很快。这样整体而言,就会达到优化的效果。
一般情况,gap的大小和分组的个数是相同的。
/**
* 希尔排序
* @param arr
*/
public static void shellSort(int[] arr) {
int gap = arr.length >> 1;
while(gap > 1) {
//不断按照Gap分组,组内按照插入排序
insertionSortGap(arr, gap);
gap /= 2;
}
//整个数组的插入排序
insertionSortGap(arr,1);
}
/**
* 按gap分组,组内按插入排序
* @param arr
* @param gap
*/
private static void insertionSortGap(int[] arr, int gap) {
//外层从gap索引处开始不断向后走到数组末尾
//i = 4
for (int i = gap; i < arr.length; i++) {
//内层从gap索引开始向前看,看的元素就是距离他gap长度的元素
//不断比较当前元素和前面gap元素的大小
//j - gap >= 0,说明前面数组还有相同距离的元素,比较arr[j] 和 arr[j - gap]的大小
//j = 9
for (int j = i; j - gap >= 0 && arr[j] < arr[j - gap] ; j = j - gap) {
swap(arr, j, j - gap);
}
}
}
i从gap开始,比较是向前比,而不是向后比:不断向前比的原因在于,这样才能把最小值放在最前面。
稳定性:不稳定。
时间复杂度:O(n^(1.2) ~ O(nlogn))